SQLite की परफ़ॉर्मेंस के लिए सबसे सही तरीके

Android, SQLite के लिए बिल्ट-इन सपोर्ट की सुविधा देता है, के हिसाब से काम करते हैं. अपने ऐप्लिकेशन के ऑप्टिमाइज़ेशन के लिए इन सबसे सही तरीकों का पालन करें ताकि यह पक्का हो सके कि डेटा बढ़ने के साथ-साथ डेटा तेज़ी से और अनुमानित रूप से तेज़ बना रहे. इन सबसे सही तरीकों का इस्तेमाल करके, जिनसे परफ़ॉर्मेंस में आने वाली ऐसी समस्याएं हों जिन्हें ठीक करना मुश्किल हो और समस्या हल करने के लिए किया जा सकता है.

बेहतर परफ़ॉर्मेंस पाने के लिए, परफ़ॉर्मेंस से जुड़ी इन नीतियों का पालन करें:

  • कम पंक्तियां और कॉलम पढ़ें: अपनी क्वेरी को इस तरह ऑप्टिमाइज़ करें कि वह सिर्फ़ पेज के ज़रूरी डेटा. डेटाबेस से पढ़े जाने वाले डेटा की मात्रा को कम करें, क्योंकि ज़्यादा डेटा वापस पाने से, परफ़ॉर्मेंस पर असर पड़ सकता है.

  • SQLite इंजन पर काम करें: कंप्यूटेशन (हिसाब लगाना), फ़िल्टर करना, और क्रम से लगाना कार्रवाइयों के लिए इस्तेमाल किया जाता है. SQLite के क्वेरी इंजन का इस्तेमाल करने से परफ़ॉर्मेंस बेहतर बनाने के लिए किया जा सकता है.

  • डेटाबेस स्कीमा में बदलाव करना: SQLite में मदद करने के लिए, अपना डेटाबेस स्कीमा डिज़ाइन करना और डेटा निरूपण बना सकते हैं. सही तरीके से इंडेक्स टेबल और टेबल स्ट्रक्चर को ऑप्टिमाइज़ करके परफ़ॉर्मेंस को बेहतर बनाएं.

इसके अलावा, समस्या को हल करने वाले उपलब्ध टूल का इस्तेमाल करके, आपके SQLite डेटाबेस की परफ़ॉर्मेंस से, उन इलाकों की पहचान करने में मदद मिलती है जहां ऑप्टिमाइज़ेशन.

हमारा सुझाव है कि आप Jetpack Room लाइब्रेरी का इस्तेमाल करें.

परफ़ॉर्मेंस के लिए डेटाबेस को कॉन्फ़िगर करें

अपने डेटाबेस को बेहतर तरीके से कॉन्फ़िगर करने के लिए, इस सेक्शन में दिया गया तरीका अपनाएं परफ़ॉर्मेंस को बेहतर बनाने के लिए किया जा सकता है.

पहले से लिखने की गतिविधि सेव करने की सुविधा चालू करें

SQLite, म्यूटेशन को लॉग में जोड़कर उन्हें लागू करता है. हालांकि, ऐसा कभी-कभी होता है छोटी हो जाती हैं. इसे लिखकर आगे बढ़ना कहा जाता है (WAL) पर टैप करें.

चालू करें वाल बशर्ते, ATTACH DATABASE का इस्तेमाल न किया जा रहा हो.

सिंक्रोनाइज़ेशन मोड को आराम दें

WAL का इस्तेमाल करने पर, हर बार fsync की समस्या को डिफ़ॉल्ट तौर पर हल किया जाता है. इससे यह पक्का करने में मदद मिलती है कि तो डेटा डिस्क तक पहुंचता है. यह डेटा टिकाऊ बनाने में मदद करता है, लेकिन आपकी साइट की परफ़ॉर्मेंस को कमिट करता है.

SQLite में सिंक्रोनस को कंट्रोल करने का विकल्प होता है मोड है. अगर आपको WAL को चालू करने के लिए, सिंक्रोनस मोड को NORMAL पर सेट करें:

Kotlin

db.execSQL("PRAGMA synchronous = NORMAL")

Java

db.execSQL("PRAGMA synchronous = NORMAL");

इस सेटिंग में, डिस्क में डेटा के सेव होने से पहले तय किया गया डेटा वापस आ सकता है. अगर कोई डिवाइस बंद हो जाता है, जैसे कि पावर खो जाने या कर्नेल घबराहट होने पर, तय डेटा खो सकता है. हालांकि, लॉगिंग के कारण, आपका डेटाबेस करप्ट है.

अगर सिर्फ़ आपका ऐप्लिकेशन क्रैश होता है, तब भी आपका डेटा डिस्क तक पहुंचता है. ज़्यादातर ऐप्लिकेशन के लिए, यह सेटिंग से, बिना किसी अतिरिक्त शुल्क के परफ़ॉर्मेंस को बेहतर बनाया जाता है.

कुशल टेबल स्कीमा तय करना

परफ़ॉर्मेंस को ऑप्टिमाइज़ करने और डेटा की खपत को कम करने के लिए, टेबल स्कीमा. SQLite, असरदार क्वेरी प्लान और डेटा बनाता है. इससे तेज़ी से डेटा वापस पाया जा सकता है. इस सेक्शन में, टेबल बनाने के सबसे सही तरीके बताए गए हैं स्कीमा शामिल करने हैं.

INTEGER PRIMARY KEY पर विचार करें

इस उदाहरण के लिए, नीचे बताए गए तरीके से टेबल तय करें और उसे अपने-आप भरे:

CREATE TABLE Customers(
  id INTEGER,
  name TEXT,
  city TEXT
);
INSERT INTO Customers Values(456, 'John Lennon', 'Liverpool, England');
INSERT INTO Customers Values(123, 'Michael Jackson', 'Gary, IN');
INSERT INTO Customers Values(789, 'Dolly Parton', 'Sevier County, TN');

टेबल का आउटपुट इस तरह का होता है:

पंक्ति आईडी id नाम शहर
1 456 जॉन लेनन लिवरपूल, इंग्लैंड
2 123 माइकल जैक्सन गैरी, इंडियाना
3 789 डॉली पार्टन सेवियर काउंटी, टेनसी

कॉलम rowid यह है वह इंडेक्स जो इंसर्शन ऑर्डर को सुरक्षित रखता है. ऐसी क्वेरी जो rowid के फ़िल्टर का इस्तेमाल करके तेज़ी से बी-ट्री खोज की जा सकती है, लेकिन id के हिसाब से फ़िल्टर करने पर, टेबल स्कैन होने में ज़्यादा समय लगता है.

अगर आप id तक लुकअप करने की योजना बना रहे हैं, तो आप कम स्टोरेज और कुल डेटा के लिए rowid कॉलम तेज़ डेटाबेस:

CREATE TABLE Customers(
  id INTEGER PRIMARY KEY,
  name TEXT,
  city TEXT
);

अब आपकी टेबल इस तरह दिखेगी:

id नाम शहर
123 माइकल जैक्सन गैरी, इंडियाना
456 जॉन लेनन लिवरपूल, इंग्लैंड
789 डॉली पार्टन सेवियर काउंटी, टेनसी

आपको rowid कॉलम को सेव करने की ज़रूरत नहीं है, इसलिए id क्वेरी तेज़ होती हैं. नोट जोड़ें कि टेबल को अब इंसर्शन ऑर्डर के बजाय id के हिसाब से क्रम में लगाया गया है.

इंडेक्स की मदद से क्वेरी की रफ़्तार बढ़ाना

SQLite का इस्तेमाल इंडेक्स का इस्तेमाल करें. फ़िल्टर (WHERE), क्रम में लगाने के लिए (ORDER BY) या (GROUP BY) कॉलम को एग्रीगेट करने, अगर टेबल में कॉलम के लिए इंडेक्स है, तो क्वेरी को आगे बढ़ाया जाता है.

पिछले उदाहरण में, city के हिसाब से फ़िल्टर करने के लिए, पूरी टेबल स्कैन करनी होगी:

SELECT id, name
WHERE city = 'London, England';

शहर से जुड़ी बहुत सारी क्वेरी वाले ऐप्लिकेशन के लिए, इसकी मदद से इंडेक्स:

CREATE INDEX city_index ON Customers(city);

इंडेक्स को एक अतिरिक्त टेबल के तौर पर लागू किया जाता है, जिसे इंडेक्स कॉलम और rowid से मैप किया गया:

शहर पंक्ति आईडी
गैरी, इंडियाना 2
लिवरपूल, इंग्लैंड 1
सेवियर काउंटी, टेनसी 3

ध्यान दें कि city कॉलम के स्टोरेज की लागत अब दोगुनी हो गई है, क्योंकि यह यह जानकारी अब ओरिजनल टेबल और इंडेक्स, दोनों में मौजूद है. चूंकि आप इंडेक्स करने के लिए कहा जाता है, तो अतिरिक्त स्टोरेज की लागत ज़्यादा तेज़ी से की जाने वाली क्वेरी के लिए फ़ायदेमंद है. हालांकि, ऐसे इंडेक्स का रखरखाव न करें जिसका इस्तेमाल आप बिना क्वेरी की परफ़ॉर्मेंस गेन के लिए स्टोरेज लागत.

एक से ज़्यादा कॉलम वाले इंडेक्स बनाएं

अगर आपकी क्वेरी में एक से ज़्यादा कॉलम जोड़े गए हैं, तो आपके पास एक से ज़्यादा कॉलम वाला कॉलम बनाने का विकल्प होता है इंडेक्स का इस्तेमाल करें. इंडेक्स का इस्तेमाल, किसी बाहरी कॉलम पर भी किया जा सकता है और आंतरिक खोज को लीनियर स्कैन की तरह किया जाना चाहिए.

उदाहरण के लिए, दी गई क्वेरी:

SELECT id, name
WHERE city = 'London, England'
ORDER BY city, name

एक से ज़्यादा कॉलम वाले इंडेक्स का इस्तेमाल करके, क्वेरी को उसी क्रम में तेज़ी से लोड किया जा सकता है क्वेरी में बताया गया है:

CREATE INDEX city_name_index ON Customers(city, name);

हालांकि, अगर आपके पास सिर्फ़ city पर इंडेक्स है, तो बाहर के क्रम में तेज़ है, जबकि अंदर के क्रम को लीनियर स्कैन की ज़रूरत होती है.

यह प्रीफ़िक्स पूछताछ के साथ भी काम करता है. उदाहरण के लिए, इंडेक्स में ON Customers (city, name) से फ़िल्टर करने, क्रम से लगाने, और ग्रुप में बांटने की सुविधा तेज़ी से काम करती है city के हिसाब से, क्योंकि एक से ज़्यादा कॉलम वाले इंडेक्स के लिए इंडेक्स टेबल दिए गए इंडेक्स को दिए गए क्रम में रखें.

WITHOUT ROWID पर विचार करें

डिफ़ॉल्ट रूप से, SQLite आपकी टेबल के लिए एक rowid कॉलम बनाता है, जहां rowid एक इंप्लिसिट INTEGER PRIMARY KEY AUTOINCREMENT. अगर आपके पास पहले से ही कोई ऐसा कॉलम है INTEGER PRIMARY KEY है, तो यह कॉलम rowid का उपनाम बन जाता है.

उन टेबल के लिए जिनमें INTEGER के अलावा कोई मुख्य कुंजी या कंपोज़िट शामिल है कॉलम, WITHOUT ROWID पर विचार करें.

छोटे डेटा को BLOB के तौर पर और बड़े डेटा को फ़ाइल के तौर पर सेव करें

अगर आपको बड़े डेटा को किसी लाइन में जोड़ना है, जैसे कि किसी इमेज का थंबनेल या संपर्क की फ़ोटो है, तो आप डेटा को BLOB कॉलम में या a फ़ाइल एक्सपोर्ट करें और फिर फ़ाइल पाथ को कॉलम में स्टोर करें.

आम तौर पर, फ़ाइलों का साइज़ 4 केबी की बढ़ोतरी तक ही किया जाता है. बहुत छोटी फ़ाइलों के लिए, जहां पूर्णांकन गड़बड़ी बड़ी है, तो उन्हें BLOB के तौर पर डेटाबेस. SQLite, फ़ाइलसिस्टम कॉल को कम करता है और यह फ़ाइल सिस्टम कुछ मामलों में.

क्वेरी की परफ़ॉर्मेंस को बेहतर बनाएं

SQLite में, क्वेरी की परफ़ॉर्मेंस को बेहतर बनाने के लिए, इन सबसे सही तरीकों को अपनाएं जवाब देने में लगने वाला समय और प्रोसेसिंग की क्षमता को ज़्यादा से ज़्यादा बढ़ाने के लिए किया जा सकता है.

सिर्फ़ अपनी ज़रूरत की लाइन पढ़ें

फ़िल्टर के ज़रिए आप कुछ खास मानदंड तय करके, नतीजों को छोटा कर सकते हैं, जैसे कि तारीख की सीमा, जगह या नाम. सीमाओं की मदद से, संख्या कंट्रोल की जा सकती है परिणामों में से आप देखते हैं:

Kotlin

db.rawQuery("""
    SELECT name
    FROM Customers
    LIMIT 10;
    """.trimIndent(),
    null
).use { cursor ->
    while (cursor.moveToNext()) {
        ...
    }
}

Java

try (Cursor cursor = db.rawQuery("""
    SELECT name
    FROM Customers
    LIMIT 10;
    """, null)) {
  while (cursor.moveToNext()) {
    ...
  }
}

अपनी ज़रूरत के हिसाब से कॉलम पढ़ें

ग़ैर-ज़रूरी कॉलम चुनने से बचें. इससे ये काम किए जा सकते हैं वे आपकी क्वेरी को धीमा कर देते हैं और संसाधनों की बर्बादी भी कम करते हैं. इसके बजाय, सिर्फ़ कॉलम चुनें जिनका इस्तेमाल किया जा चुका हो.

यहां दिए गए उदाहरण में, id, name, और phone को चुना गया है:

Kotlin

// This is not the most efficient way of doing this.
// See the following example for a better approach.

db.rawQuery(
    """
    SELECT id, name, phone
    FROM customers;
    """.trimIndent(),
    null
).use { cursor ->
    while (cursor.moveToNext()) {
        val name = cursor.getString(1)
        // ...
    }
}

Java

// This is not the most efficient way of doing this.
// See the following example for a better approach.

try (Cursor cursor = db.rawQuery("""
    SELECT id, name, phone
    FROM customers;
    """, null)) {
  while (cursor.moveToNext()) {
    String name = cursor.getString(1);
    ...
  }
}

हालांकि, आपको सिर्फ़ name कॉलम की ज़रूरत है:

Kotlin

db.rawQuery("""
    SELECT name
    FROM Customers;
    """.trimIndent(),
    null
).use { cursor ->
    while (cursor.moveToNext()) {
        val name = cursor.getString(0)
        ...
    }
}

Java

try (Cursor cursor = db.rawQuery("""
    SELECT name
    FROM Customers;
    """, null)) {
  while (cursor.moveToNext()) {
    String name = cursor.getString(0);
    ...
  }
}

यूनीक वैल्यू के लिए DISTINCT का इस्तेमाल करें

DISTINCT कीवर्ड का इस्तेमाल करने से आपकी क्वेरी की परफ़ॉर्मेंस बेहतर हो सकती है प्रोसेस किए जाने वाले डेटा की मात्रा को कम कर देगा. उदाहरण के लिए, अगर आपको किसी कॉलम से सिर्फ़ यूनीक वैल्यू दिखाने के लिए, DISTINCT का इस्तेमाल करें:

Kotlin

db.rawQuery("""
    SELECT DISTINCT name
    FROM Customers;
    """.trimIndent(),
    null
).use { cursor ->
    while (cursor.moveToNext()) {
        // Only iterate over distinct names in Kotlin
        ...
    }
}

Java

try (Cursor cursor = db.rawQuery("""
    SELECT DISTINCT name
    FROM Customers;
    """, null)) {
  while (cursor.moveToNext()) {
    // Only iterate over distinct names in Java
    ...
  }
}

जब भी हो सके, एग्रीगेट फ़ंक्शन का इस्तेमाल करें

पंक्ति डेटा के बिना एग्रीगेट नतीजों के लिए एग्रीगेट फ़ंक्शन का इस्तेमाल करें. उदाहरण के लिए, नीचे दिए गए कोड से पता चलता है कि मेल खाने वाली कम से कम एक पंक्ति मौजूद है या नहीं:

Kotlin

// This is not the most efficient way of doing this.
// See the following example for a better approach.

db.rawQuery("""
    SELECT id, name
    FROM Customers
    WHERE city = 'Paris';
    """.trimIndent(),
    null
).use { cursor ->
    if (cursor.moveToFirst()) {
        // At least one customer from Paris
        ...
    } else {
        // No customers from Paris
        ...
}

Java

// This is not the most efficient way of doing this.
// See the following example for a better approach.

try (Cursor cursor = db.rawQuery("""
    SELECT id, name
    FROM Customers
    WHERE city = 'Paris';
    """, null)) {
  if (cursor.moveToFirst()) {
    // At least one customer from Paris
    ...
  } else {
    // No customers from Paris
    ...
  }
}

सिर्फ़ पहली लाइन को फ़ेच करने के लिए, EXISTS() का इस्तेमाल करके 0 दिया जा सकता है. ऐसा तब किया जा सकता है, जब वैल्यू मेल खाती हो पंक्ति मौजूद नहीं है और 1 अगर एक या ज़्यादा पंक्तियां मेल खाती हैं, तो:

Kotlin

db.rawQuery("""
    SELECT EXISTS (
        SELECT null
        FROM Customers
        WHERE city = 'Paris';
    );
    """.trimIndent(),
    null
).use { cursor ->
    if (cursor.moveToFirst() && cursor.getInt(0) == 1) {
        // At least one customer from Paris
        ...
    } else {
        // No customers from Paris
        ...
    }
}

Java

try (Cursor cursor = db.rawQuery("""
    SELECT EXISTS (
      SELECT null
      FROM Customers
      WHERE city = 'Paris'
    );
    """, null)) {
  if (cursor.moveToFirst() && cursor.getInt(0) == 1) {
    // At least one customer from Paris
    ...
  } else {
    // No customers from Paris
    ...
  }
}

SQLite एग्रीगेट का इस्तेमाल करना फ़ंक्शन में बदलाव कर सकते हैं कोड:

  • COUNT: यह गिनता है कि कॉलम में कितनी पंक्तियां हैं.
  • SUM: यह किसी कॉलम में संख्या वाली सभी वैल्यू जोड़ता है.
  • MIN या MAX: यह सबसे कम या सबसे बड़ी वैल्यू तय करता है. न्यूमेरिक के लिए काम करता है कॉलम, DATE टाइप और टेक्स्ट टाइप.
  • AVG: औसत संख्या वाली वैल्यू का पता लगाता है.
  • GROUP_CONCAT: सेपरेटर की मदद से स्ट्रिंग को जोड़ता है.

Cursor.getCount() के बजाय COUNT() का इस्तेमाल करें

इस नीचे दिए गए उदाहरण में, Cursor.getCount() फ़ंक्शन डेटाबेस की सभी लाइन को पढ़ता है और लाइन की सभी वैल्यू दिखाता है:

Kotlin

// This is not the most efficient way of doing this.
// See the following example for a better approach.

db.rawQuery("""
    SELECT id
    FROM Customers;
    """.trimIndent(),
    null
).use { cursor ->
    val count = cursor.getCount()
}

Java

// This is not the most efficient way of doing this.
// See the following example for a better approach.

try (Cursor cursor = db.rawQuery("""
    SELECT id
    FROM Customers;
    """, null)) {
  int count = cursor.getCount();
  ...
}

हालांकि, COUNT() का इस्तेमाल करने पर डेटाबेस संख्या:

Kotlin

db.rawQuery("""
    SELECT COUNT(*)
    FROM Customers;
    """.trimIndent(),
    null
).use { cursor ->
    cursor.moveToFirst()
    val count = cursor.getInt(0)
}

Java

try (Cursor cursor = db.rawQuery("""
    SELECT COUNT(*)
    FROM Customers;
    """, null)) {
  cursor.moveToFirst();
  int count = cursor.getInt(0);
  ...
}

कोड के बजाय Nest क्वेरी

एसक्यूएल को कंपोज़ किया जा सकता है और यह सबक्वेरी, जॉइन, और फ़ॉरेन की कंस्ट्रेंट के साथ काम करता है. ऐप्लिकेशन पर जाए बिना, एक क्वेरी के नतीजे को दूसरी क्वेरी में इस्तेमाल किया जा सकता है कोड. इससे SQLite से डेटा कॉपी करने की ज़रूरत कम हो जाती है और डेटाबेस इंजन आपकी क्वेरी को ऑप्टिमाइज़ करता है.

नीचे दिए गए उदाहरण में, क्वेरी चलाकर यह पता लगाया जा सकता है कि किस शहर में सबसे ज़्यादा इसके बाद, किसी दूसरी क्वेरी के नतीजे का इस्तेमाल करके, उस शहर:

Kotlin

// This is not the most efficient way of doing this.
// See the following example for a better approach.

db.rawQuery("""
    SELECT city
    FROM Customers
    GROUP BY city
    ORDER BY COUNT(*) DESC
    LIMIT 1;
    """.trimIndent(),
    null
).use { cursor ->
    if (cursor.moveToFirst()) {
        val topCity = cursor.getString(0)
        db.rawQuery("""
            SELECT name, city
            FROM Customers
            WHERE city = ?;
        """.trimIndent(),
        arrayOf(topCity)).use { innerCursor ->
            while (innerCursor.moveToNext()) {
                ...
            }
        }
    }
}

Java

// This is not the most efficient way of doing this.
// See the following example for a better approach.

try (Cursor cursor = db.rawQuery("""
    SELECT city
    FROM Customers
    GROUP BY city
    ORDER BY COUNT(*) DESC
    LIMIT 1;
    """, null)) {
  if (cursor.moveToFirst()) {
    String topCity = cursor.getString(0);
    try (Cursor innerCursor = db.rawQuery("""
        SELECT name, city
        FROM Customers
        WHERE city = ?;
        """, new String[] {topCity})) {
        while (innerCursor.moveToNext()) {
          ...
        }
    }
  }
}

पिछले उदाहरण के आधे समय में नतीजा पाने के लिए, एक एसक्यूएल का इस्तेमाल करें नेस्ट किए गए स्टेटमेंट वाली क्वेरी:

Kotlin

db.rawQuery("""
    SELECT name, city
    FROM Customers
    WHERE city IN (
        SELECT city
        FROM Customers
        GROUP BY city
        ORDER BY COUNT (*) DESC
        LIMIT 1;
    );
    """.trimIndent(),
    null
).use { cursor ->
    if (cursor.moveToNext()) {
        ...
    }
}

Java

try (Cursor cursor = db.rawQuery("""
    SELECT name, city
    FROM Customers
    WHERE city IN (
      SELECT city
      FROM Customers
      GROUP BY city
      ORDER BY COUNT(*) DESC
      LIMIT 1
    );
    """, null)) {
  while(cursor.moveToNext()) {
    ...
  }
}

एसक्यूएल में यूनीक वैल्यू की जांच करना

अगर कोई पंक्ति तब तक नहीं डाली जानी चाहिए, जब तक कि कॉलम का कोई खास मान टेबल है, तो एक कॉलम के तौर पर उस खासियत को लागू करना ज़्यादा कारगर साबित हो सकता है कंस्ट्रेंट.

नीचे दिए गए उदाहरण में, एक क्वेरी चलाई गई है, ताकि लाइन और अन्य को वास्तव में शामिल करने के लिए:

Kotlin

// This is not the most efficient way of doing this.
// See the following example for a better approach.

db.rawQuery(
    """
    SELECT EXISTS (
        SELECT null
        FROM customers
        WHERE username = ?
    );
    """.trimIndent(),
    arrayOf(customer.username)
).use { cursor ->
    if (cursor.moveToFirst() && cursor.getInt(0) == 1) {
        throw AddCustomerException(customer)
    }
}
db.execSQL(
    "INSERT INTO customers VALUES (?, ?, ?)",
    arrayOf(
        customer.id.toString(),
        customer.name,
        customer.username
    )
)

Java

// This is not the most efficient way of doing this.
// See the following example for a better approach.

try (Cursor cursor = db.rawQuery("""
    SELECT EXISTS (
      SELECT null
      FROM customers
      WHERE username = ?
    );
    """, new String[] { customer.username })) {
  if (cursor.moveToFirst() && cursor.getInt(0) == 1) {
    throw new AddCustomerException(customer);
  }
}
db.execSQL(
    "INSERT INTO customers VALUES (?, ?, ?)",
    new String[] {
      String.valueOf(customer.id),
      customer.name,
      customer.username,
    });

Kotlin या Java में यूनीक कंस्ट्रेंट की जांच करने के बजाय, इसे चेक किया जा सकता है टेबल तय करते समय एसक्यूएल:

CREATE TABLE Customers(
  id INTEGER PRIMARY KEY,
  name TEXT,
  username TEXT UNIQUE
);

SQLite ऐसा ही करता है:

CREATE TABLE Customers(...);
CREATE UNIQUE INDEX CustomersUsername ON Customers(username);

अब एक पंक्ति डाली जा सकती है और SQLite को कंस्ट्रेंट की जांच करने दिया जा सकता है:

Kotlin

try {
    db.execSql(
        "INSERT INTO Customers VALUES (?, ?, ?)",
        arrayOf(customer.id.toString(), customer.name, customer.username)
    )
} catch(e: SQLiteConstraintException) {
    throw AddCustomerException(customer, e)
}

Java

try {
  db.execSQL(
      "INSERT INTO Customers VALUES (?, ?, ?)",
      new String[] {
        String.valueOf(customer.id),
        customer.name,
        customer.username,
      });
} catch (SQLiteConstraintException e) {
  throw new AddCustomerException(customer, e);
}

SQLite, कई कॉलम वाले यूनीक इंडेक्स के साथ काम करता है:

CREATE TABLE table(...);
CREATE UNIQUE INDEX unique_table ON table(column1, column2, ...);

SQLite, Kotlin या Java की तुलना में कम ओवरहेड के साथ, कंस्ट्रेंट की तेज़ी से पुष्टि करता है कोड. ऐप्लिकेशन कोड के बजाय, SQLite का इस्तेमाल करना सबसे सही तरीका है.

एक ही ट्रांज़ैक्शन में एक से ज़्यादा बार शामिल करने की सुविधा

एक ट्रांज़ैक्शन में कई कार्रवाइयां होती हैं. इससे न सिर्फ़ परफ़ॉर्मेंस, बल्कि सटीक जानकारी भी. डेटा को एक जैसा रखने और परफ़ॉर्मेंस बढ़ाने के लिए, बैच इंसर्शन की सुविधा का इस्तेमाल किया जा सकता है:

Kotlin

db.beginTransaction()
try {
    customers.forEach { customer ->
        db.execSql(
            "INSERT INTO Customers VALUES (?, ?, ...)",
            arrayOf(customer.id.toString(), customer.name, ...)
        )
    }
} finally {
    db.endTransaction()
}

Java

db.beginTransaction();
try {
  for (customer : Customers) {
    db.execSQL(
        "INSERT INTO Customers VALUES (?, ?, ...)",
        new String[] {
          String.valueOf(customer.id),
          customer.name,
          ...
        });
  }
} finally {
  db.endTransaction()
}

समस्या हल करने वाले टूल इस्तेमाल करना

SQLite, परफ़ॉर्मेंस को मेज़र करने के लिए, समस्या हल करने वाले ये टूल उपलब्ध कराता है.

SQLite के इंटरैक्टिव प्रॉम्प्ट का इस्तेमाल करें

क्वेरी चलाने और सीखने के लिए, अपनी मशीन पर SQLite चलाएं. Android प्लैटफ़ॉर्म के अलग-अलग वर्शन में, SQLite के अलग-अलग बदलावों का इस्तेमाल किया जाता है. इस्तेमाल करने के लिए जो Android डिवाइस में काम करता है, उसी इंजन के लिए adb shell और अपने टारगेट डिवाइस पर sqlite3 चलाएं.

SQLite से समय की क्वेरी के लिए पूछा जा सकता है:

sqlite> .timer on
sqlite> SELECT ...
Run Time: real ... user ... sys ...

EXPLAIN QUERY PLAN

SQLite से, यह जानने के लिए कहा जा सकता है कि वह किसी क्वेरी का जवाब कैसे देना चाहता है EXPLAIN QUERY PLAN:

sqlite> EXPLAIN QUERY PLAN
SELECT id, name
FROM Customers
WHERE city = 'Paris';
QUERY PLAN
`--SCAN Customers

पिछले उदाहरण में, सभी को ढूंढने के लिए इंडेक्स के बिना पूरी टेबल स्कैन करना ज़रूरी है दिल्ली के ग्राहक. इसे लीनियर कॉम्प्लेक्सिटी कहा जाता है. SQLite को पढ़ना ज़रूरी है सभी पंक्तियों को शामिल करें. साथ ही, सिर्फ़ वे पंक्तियां रखें जो पेरिस के ग्राहकों से मेल खाती हों. समस्या ठीक करने के लिए तब इंडेक्स जोड़ा जा सकता है:

sqlite> CREATE INDEX Idx1 ON Customers(city);
sqlite> EXPLAIN QUERY PLAN
SELECT id, name
FROM Customers
WHERE city = 'Paris';
QUERY PLAN
`--SEARCH test USING INDEX Idx1 (city=?

अगर इंटरैक्टिव शेल का इस्तेमाल किया जा रहा है, तो SQLite से कहें कि वह हमेशा क्वेरी प्लान:

sqlite> .eqp on

ज़्यादा जानकारी के लिए, यह देखें क्वेरी प्लानिंग.

SQLite ऐनालाइज़र

SQLite, sqlite3_analyzer कमांड-लाइन इंटरफ़ेस (सीएलआई) का इस्तेमाल करता है. इसका इस्तेमाल परफ़ॉर्मेंस से जुड़ी समस्या हल करें. इंस्टॉल करने के लिए, इस लिंक पर जाएं SQLite डाउनलोड पेज.

adb pull का इस्तेमाल करके, टारगेट किए गए डिवाइस से डेटाबेस फ़ाइल डाउनलोड की जा सकती है विश्लेषण के लिए वर्कस्टेशन:

adb pull /data/data/<app_package_name>/databases/<db_name>.db

SQLite ब्राउज़र

इसके अलावा, जीयूआई टूल भी इंस्टॉल किया जा सकता है. SQLite पर SQLite ब्राउज़र डाउनलोड पेज.

Android में लॉग इन करने की सुविधा

Android के बार, SQLite से क्वेरी और आपके लिए उन्हें लॉग किया जाता है:

# Enable query time logging
$ adb shell setprop log.tag.SQLiteTime VERBOSE
# Disable query time logging
$ adb shell setprop log.tag.SQLiteTime ERROR
```### Perfetto tracing

### Perfetto tracing {:#perfetto-tracing}

When [configuring Perfetto](https://perfetto.dev/docs/concepts/config), you may
add the following to include tracks for individual queries:

```protobuf
data_sources {
  config {
    name: "linux.ftrace"
    ftrace_config {
      atrace_categories: "database"
    }
  }
}