Android, verimli bir SQL veritabanı olan SQLite için yerleşik destek sunar. Uygulamanızın performansını optimize etmek için aşağıdaki en iyi uygulamaları uygulayarak verileriniz arttıkça hızlı ve tahmin edilebilir bir şekilde hızlı kalmasını sağlayın. Bu en iyi uygulamaları kullanarak, yeniden oluşturması ve sorunlarını gidermesi zor performans sorunlarınla karşılaşma olasılığını da azaltırsınız.
Daha hızlı performans elde etmek için aşağıdaki performans ilkelerini uygulayın:
Daha az satır ve sütun okuma: Sorgularınızı yalnızca gerekli verileri alacak şekilde optimize edin. Fazla veri alma performansı etkileyebileceğinden, veritabanından okunan veri miktarını en aza indirin.
İşi SQLite motoruna gönderin: SQL sorgularında hesaplama, filtreleme ve sıralama işlemleri gerçekleştirin. SQLite'in sorgu motorunu kullanmak performansı önemli ölçüde artırabilir.
Veritabanı şemasını değiştirme: Veritabanı şemanızı, SQLite'in etkili sorgu planları ve veri temsilleri oluşturmasına yardımcı olacak şekilde tasarlayın. Tabloları doğru şekilde dizine ekleyin ve performansı artırmak için tablo yapılarını optimize edin.
Ayrıca, optimizasyon gerektiren alanları belirlemek için SQLite veritabanınızın performansını ölçmek üzere mevcut sorun giderme araçlarını kullanabilirsiniz.
Jetpack Room kitaplığını kullanmanızı öneririz.
Veritabanını performans için yapılandırma
Veritabanını SQLite'te optimum performans için yapılandırmak üzere bu bölümdeki adımları uygulayın.
Önceden Yazma Günlük Kaydını Etkinleştirme
SQLite, mutasyonları bir günlüke ekleyerek uygular ve bu günlük zaman zaman veritabanında sıkıştırılır. Buna önceden yazma günlüğü (WAL) denir.
ATTACH
DATABASE
kullanmıyorsanız WAL'ı etkinleştirin.
Senkronizasyon modunu gevşetme
WAL kullanılırken varsayılan olarak her bir taahhüt, verilerin diske ulaşmasını sağlamak için bir fsync
yayınlar. Bu, verilerin dayanıklılığını artırır ancak taahhütlerinizi yavaşlatır.
SQLite'te senkron modunu kontrol etme seçeneği vardır. WAL'yi etkinleştirirseniz senkronize modu NORMAL
olarak ayarlayın:
Kotlin
db.execSQL("PRAGMA synchronous = NORMAL")
Java
db.execSQL("PRAGMA synchronous = NORMAL");
Bu ayarda, veriler diske kaydedilmeden önce bir taahhüt döndürülebilir. Güç kaybı veya çekirdek paniği gibi durumlarda cihaz kapanırsa tescilli veriler kaybolabilir. Ancak günlük kaydı sayesinde veritabanınız bozulmadı.
Yalnızca uygulamanız kilitlenirse verileriniz diske ulaşır. Çoğu uygulama için bu ayar, önemli bir maliyete yol açmadan performans iyileştirmeleri sağlar.
Verimli tablo şemaları tanımlama
Performansı optimize etmek ve veri tüketimini en aza indirmek için verimli bir tablo şeması tanımlayın. SQLite, verimli sorgu planları ve veriler oluşturur. Bu da daha hızlı veri almayla sonuçlanır. Bu bölümde, tablo şemaları oluşturmayla ilgili en iyi uygulamalar yer almaktadır.
INTEGER PRIMARY KEY
Bu örnekte, bir tabloyu aşağıdaki gibi tanımlayıp doldurun:
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');
Tablo çıkışı şu şekildedir:
rowid | id | ad | şehir |
---|---|---|---|
1 | 456 | John Lennon | Liverpool, İngiltere |
2 | 123 | Michael Jackson | Gary, Indiana |
3 | 789 | Dolly Parton | Sevier County, TN |
rowid
sütunu, kampanya siparişini koruyan bir dizindir. rowid
değerine göre filtrelenen sorgular hızlı bir B ağacı araması olarak uygulanır ancak id
değerine göre filtrelenen sorgular yavaş bir tablo taraması olarak uygulanır.
id
değerine göre arama yapmayı planlıyorsanız depolama alanında daha az veri ve genel olarak daha hızlı bir veritabanı için rowid
sütununu depolamamaktan kaçınabilirsiniz:
CREATE TABLE Customers(
id INTEGER PRIMARY KEY,
name TEXT,
city TEXT
);
Tablonuz artık aşağıdaki gibi görünür:
id | ad | şehir |
---|---|---|
123 | Michael Jackson | Gary, Indiana |
456 | John Lennon | Liverpool, İngiltere |
789 | Dolly Parton | Sevier County, TN |
rowid
sütununu depolamanıza gerek olmadığından id
sorguları hızlıdır. Tablonun artık kampanya siparişi yerine id
'ye göre sıralandığını unutmayın.
Dizinlerle sorguları hızlandırma
SQLite, sorguları hızlandırmak için dizinler kullanır. Bir sütun filtrelenirken (WHERE
), sıralanırken (ORDER BY
) veya toplanırken (GROUP BY
), tabloda sütun için bir dizin varsa sorgu hızlandırılır.
Önceki örnekte, city
değerine göre filtreleme yapmak için tablonun tamamının taranması gerekir:
SELECT id, name
WHERE city = 'London, England';
Çok sayıda şehir sorgusu olan bir uygulamada, bu sorguları bir dizinle hızlandırabilirsiniz:
CREATE INDEX city_index ON Customers(city);
Dizin, dizin sütununa göre sıralanmış ve rowid
ile eşlenmiş ek bir tablo olarak uygulanır:
şehir | rowid |
---|---|
Gary, Indiana | 2 |
Liverpool, İngiltere | 1 |
Sevier County, TN | 3 |
city
sütununun depolama maliyetinin artık iki katı olduğunu unutmayın çünkü artık hem orijinal tabloda hem de dizinde mevcuttur. Dizin kullandığınızdan, ek depolama alanı maliyeti daha hızlı sorguların avantajına değer.
Ancak, sorgu performansında herhangi bir artış elde etmeden depolama alanı maliyeti ödememek için kullanmadığınız bir dizini muhafaza etmeyin.
Çok sütunlu dizinler oluşturma
Sorgularınız birden fazla sütunu birleştiriyorsa sorguyu tamamen hızlandırmak için çok sütunlu dizinler oluşturabilirsiniz. Dıştaki bir sütunda dizin de kullanabilir ve iç aramanın doğrusal tarama olarak yapılmasına izin verebilirsiniz.
Örneğin, aşağıdaki sorgu verildiğinde:
SELECT id, name
WHERE city = 'London, England'
ORDER BY city, name
Sorguda belirtilen sırayla çok sütunlu bir dizin kullanarak sorguyu hızlandırabilirsiniz:
CREATE INDEX city_name_index ON Customers(city, name);
Ancak yalnızca city
üzerinde bir dizininiz varsa dış sipariş yine de hızlandırılır. İç sipariş ise doğrusal tarama gerektirir.
Bu yöntem, ön ek sorguları için de geçerlidir. Örneğin, çok sütunlu bir dizinin dizin tablosu, belirli dizine göre belirli bir sırada sıralandığından ON Customers (city, name)
dizini, city
'ye göre filtreleme, sıralama ve gruplandırma işlemlerini de hızlandırır.
WITHOUT ROWID
SQLite, varsayılan olarak tablonuz için bir rowid
sütunu oluşturur. Burada rowid
, gizli bir INTEGER PRIMARY KEY AUTOINCREMENT
olur. INTEGER PRIMARY KEY
adlı bir sütununuz varsa bu sütun rowid
için bir takma ad olur.
INTEGER
dışında bir birincil anahtarı veya sütunlardan oluşan bir bileşimi olan tablolar için WITHOUT
ROWID
seçeneğini kullanın.
Küçük verileri BLOB
olarak, büyük verileri ise dosya olarak depolama
Bir satırla ilişkilendirmek istediğiniz büyük verileri (ör. bir resmin küçük resmi veya bir kişinin fotoğrafı) BLOB
sütununda ya da bir dosyada saklayabilir ve ardından dosya yolunu sütunda saklayabilirsiniz.
Dosyalar genellikle 4 KB'lık artışlarla yuvarlanır. Yuvarlama hatasının önemli olduğu çok küçük dosyaları veritabanında BLOB
olarak depolamak daha verimlidir. SQLite, dosya sistemi çağrılarını en aza indirir ve bazı durumlarda temel dosya sisteminden daha hızlıdır.
Sorgu performansını iyileştirme
Yanıt sürelerini en aza indirip işleme verimliliğini en üst düzeye çıkararak SQLite'teki sorgu performansını iyileştirmek için aşağıdaki en iyi uygulamaları izleyin.
Yalnızca ihtiyacınız olan satırları okuma
Filtreler, tarih aralığı, konum veya ad gibi belirli ölçütleri belirterek sonuçlarınızı daraltmanıza olanak tanır. Sınırlar, gördüğünüz sonuç sayısını kontrol etmenizi sağlar:
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()) { ... } }
Yalnızca ihtiyacınız olan sütunları okuma
Sorgularınızı yavaşlatabilecek ve kaynakları boşa harcayabilecek gereksiz sütunları seçmekten kaçının. Bunun yerine, yalnızca kullanılan sütunları seçin.
Aşağıdaki örnekte id
, name
ve phone
öğelerini seçersiniz:
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); ... } }
Ancak yalnızca name
sütununa ihtiyacınız vardır:
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); ... } }
Sorguları dize birleştirme yerine SQL kartlarıyla parametrelendirin
Sorgu diziniz yalnızca çalışma zamanında bilinen bir parametre içerebilir. Örneğin:
Kotlin
fun getNameById(id: Long): String? db.rawQuery( "SELECT name FROM customers WHERE id=$id", null ).use { cursor -> return if (cursor.moveToFirst()) { cursor.getString(0) } else { null } } }
Java
@Nullable public String getNameById(long id) { try (Cursor cursor = db.rawQuery( "SELECT name FROM customers WHERE id=" + id, null)) { if (cursor.moveToFirst()) { return cursor.getString(0); } else { return null; } } }
Önceki kodda her sorgu farklı bir dize oluşturur ve bu nedenle ifade önbelleğinden yararlanmaz. Her çağrının yürütülebilmesi için SQLite'nin derlenmesi gerekir. Bunun yerine, id
bağımsız değişkenini bir parametre ile değiştirebilir ve değeri selectionArgs
ile bağlayabilirsiniz:
Kotlin
fun getNameById(id: Long): String? { db.rawQuery( """ SELECT name FROM customers WHERE id=? """.trimIndent(), arrayOf(id.toString()) ).use { cursor -> return if (cursor.moveToFirst()) { cursor.getString(0) } else { null } } }
Java
@Nullable public String getNameById(long id) { try (Cursor cursor = db.rawQuery(""" SELECT name FROM customers WHERE id=? """, new String[] {String.valueOf(id)})) { if (cursor.moveToFirst()) { return cursor.getString(0); } else { return null; } } }
Artık sorgu bir kez derlenebilir ve önbelleğe alınabilir. Derlenen sorgu, getNameById(long)
'ün farklı çağrıları arasında yeniden kullanılır.
Kodda değil, SQL'de iterasyon yapın
Tek tek sonuçlar döndürmek için SQL sorgularını yineleyen programatik bir döngü yerine, hedeflenen tüm sonuçları döndüren tek bir sorgu kullanın. Programatik döngü, tek bir SQL sorgusundan yaklaşık 1.000 kat daha yavaştır.
Benzersiz değerler için DISTINCT
kullanın
DISTINCT
anahtar kelimesini kullanmak, işlenecek veri miktarını azaltarak sorgularınızın performansını artırabilir. Örneğin, bir sütundaki yalnızca benzersiz değerleri döndürmek istiyorsanız DISTINCT
kullanın:
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 ... } }
Mümkün olduğunda toplama işlevlerini kullanın
Satır verileri içermeyen toplu sonuçlar için toplama işlevlerini kullanın. Örneğin, aşağıdaki kod en az bir eşleşen satır olup olmadığını kontrol eder:
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 ... } }
Yalnızca ilk satırı almak için eşleşen bir satır yoksa 0
, bir veya daha fazla satır eşleşirse 1
döndürmek üzere EXISTS()
kullanabilirsiniz:
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 ... } }
Uygulama kodunuzda SQLite toplu işlevlerini kullanın:
COUNT
: Bir sütundaki satır sayısını hesaplar.SUM
: Bir sütundaki tüm sayısal değerleri toplar.MIN
veyaMAX
: En düşük veya en yüksek değeri belirler. Sayısal sütunlar,DATE
türleri ve metin türleri için çalışır.AVG
: Ortalama sayısal değeri bulur.GROUP_CONCAT
: Dizeleri isteğe bağlı bir ayırıcıyla birleştirir.
Cursor.getCount()
yerine COUNT()
kullanın
Aşağıdaki örnekte, Cursor.getCount()
işlevi veritabanındaki tüm satırları okur ve tüm satır değerlerini döndürür:
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(); ... }
Ancak COUNT()
kullanıldığında veritabanı yalnızca sayıyı döndürür:
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); ... }
Kod yerine Nest sorguları
SQL, birleştirilebilir ve alt sorgular, birleştirme işlemleri ve yabancı anahtar kısıtlamalarını destekler. Uygulama koduna girmeden bir sorgunun sonucunu başka bir sorguda kullanabilirsiniz. Bu sayede, SQLite'ten veri kopyalama ihtiyacı azalır ve veritabanı motoru sorgunuzu optimize edebilir.
Aşağıdaki örnekte, en çok müşterinin hangi şehirde olduğunu bulmak için bir sorgu çalıştırabilir ve ardından bu şehirdeki tüm müşterileri bulmak için sonucu başka bir sorguda kullanabilirsiniz:
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()) { ... } } } }
Sonucu önceki örneğin yarısı kadar sürede almak için iç içe yerleştirilmiş ifadeler içeren tek bir SQL sorgusu kullanın:
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()) { ... } }
SQL'de benzersizliği kontrol etme
Belirli bir sütun değeri tabloda benzersiz olmadığı sürece satır eklenmemesi gerekiyorsa bu benzersizliği sütun kısıtlaması olarak zorunlu kılmak daha verimli olabilir.
Aşağıdaki örnekte, eklenecek satırı doğrulamak için bir sorgu, gerçekten eklemek için de başka bir sorgu çalıştırılır:
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, });
Benzersiz kısıtlamayı Kotlin veya Java'da kontrol etmek yerine, tabloyu tanımlarken SQL'de kontrol edebilirsiniz:
CREATE TABLE Customers(
id INTEGER PRIMARY KEY,
name TEXT,
username TEXT UNIQUE
);
SQLite, aşağıdakiyle aynı işlemi yapar:
CREATE TABLE Customers(...);
CREATE UNIQUE INDEX CustomersUsername ON Customers(username);
Artık bir satır ekleyebilir ve SQLite'in kısıtlamayı kontrol etmesine izin verebilirsiniz:
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, birden çok sütun içeren benzersiz dizinleri destekler:
CREATE TABLE table(...);
CREATE UNIQUE INDEX unique_table ON table(column1, column2, ...);
SQLite, kısıtlamaları Kotlin veya Java koduna kıyasla daha hızlı ve daha az ek maliyetle doğrular. Uygulama kodu yerine SQLite kullanmak en iyi uygulamadır.
Tek bir işlemde birden fazla kampanya ekleme işlemini toplu olarak gerçekleştirme
İşlem, birden fazla işlemi taahhüt eder. Bu, yalnızca verimliliği değil doğruluğu da artırır. Veri tutarlılığını iyileştirmek ve performansı artırmak için eklemeleri toplu olarak yapabilirsiniz:
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() }
Sorun giderme araçlarını kullanma
SQLite, performansı ölçmenize yardımcı olmak için aşağıdaki sorun giderme araçlarını sağlar.
SQLite'in etkileşimli istemlerini kullanma
Sorgu çalıştırmak ve öğrenmek için makinenizde SQLite'i çalıştırın.
Farklı Android platform sürümleri, SQLite'in farklı düzeltmelerini kullanır. Android destekli bir cihazdakiyle aynı motoru kullanmak için adb shell
kullanın ve hedef cihazınızda sqlite3
'ı çalıştırın.
SQLite'ten sorguları zamanlamasını isteyebilirsiniz:
sqlite> .timer on
sqlite> SELECT ...
Run Time: real ... user ... sys ...
EXPLAIN QUERY PLAN
EXPLAIN QUERY PLAN
kullanarak SQLite'ten bir sorguyu nasıl yanıtlamayı planladığını açıklamasını isteyebilirsiniz:
sqlite> EXPLAIN QUERY PLAN
SELECT id, name
FROM Customers
WHERE city = 'Paris';
QUERY PLAN
`--SCAN Customers
Önceki örnekte, Paris'teki tüm müşterileri bulmak için dizin olmadan tam tablo taraması gerekir. Buna doğrusal karmaşıklık denir. SQLite'in tüm satırları okuması ve yalnızca Paris'teki müşterilerle eşleşen satırları tutması gerekir. Bu sorunu düzeltmek için dizin ekleyebilirsiniz:
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=?
Etkileşimli kabuğu kullanıyorsanız SQLite'ten sorgu planlarını her zaman açıklamasını isteyebilirsiniz:
sqlite> .eqp on
Daha fazla bilgi için Sorgu Planlama bölümüne bakın.
SQLite Analiz Aracı
SQLite, performans sorunlarını gidermek için kullanılabilecek ek bilgileri dökmek amacıyla sqlite3_analyzer
komut satırı arayüzünü (KSA) sunar. Yüklemek için SQLite İndirme Sayfası'nı ziyaret edin.
Bir veritabanı dosyasını hedef cihazdan analiz için iş istasyonunuza indirmek üzere adb pull
'ü kullanabilirsiniz:
adb pull /data/data/<app_package_name>/databases/<db_name>.db
SQLite Tarayıcı
SQLite İndirilenler sayfasından SQLite Tarayıcı GUI aracını da yükleyebilirsiniz.
Android günlük kaydı
Android, SQLite sorgularını zamanlayıp sizin için günlüğe kaydeder:
# Enable query time logging
$ adb shell setprop log.tag.SQLiteTime VERBOSE
# Disable query time logging
$ adb shell setprop log.tag.SQLiteTime ERROR
Perfetto izleme
Perfetto'yu yapılandırırken, bağımsız sorgular için kanallar eklemek üzere aşağıdakileri ekleyebilirsiniz:
data_sources {
config {
name: "linux.ftrace"
ftrace_config {
atrace_categories: "database"
}
}
}
Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir
- Sürekli entegrasyonda karşılaştırma çalıştırma
- Donmuş kare
- Makro Karşılaştırma olmadan referans profilleri oluşturma ve ölçme