SQLite'─▒n saniyede INSERT performans─▒n─▒ artt─▒rmak?


Al─▒nan cevaba git


SQLite'─▒ optimize etmek zor. Bir C uygulamas─▒n─▒n toplu ekleme performans─▒ saniyede 85 u├ž ila saniyede 96.000 u├žtan farkl─▒ olabilir!

Arka plan: Bir masa├╝st├╝ uygulamas─▒n─▒n par├žas─▒ olarak SQLite kullan─▒yoruz. Uygulama ba┼člat─▒ld─▒─č─▒nda daha fazla i┼člem yapmak ├╝zere ayr─▒┼čt─▒r─▒lan ve bir SQLite veritaban─▒na y├╝klenen XML dosyalar─▒nda depolanan b├╝y├╝k miktarda yap─▒land─▒rma verisine sahibiz. SQLite bu durum i├žin idealdir ├ž├╝nk├╝ h─▒zl─▒d─▒r, ├Âzel bir konfig├╝rasyon gerektirmez ve veritaban─▒ tek bir dosya olarak diskte depolan─▒r.

Gerek├že: Ba┼člang─▒├žta g├Ârd├╝─č├╝m performans beni hayal k─▒r─▒kl─▒─č─▒na u─čratt─▒. Veritaban─▒n─▒n nas─▒l yap─▒land─▒r─▒ld─▒─č─▒na ve API'yi nas─▒l kulland─▒─č─▒n─▒za ba─čl─▒ olarak, SQLite'in performans─▒n─▒n ├Ânemli ├Âl├ž├╝de de─či┼čebilece─či (toplu ekleme ve se├žme i┼člemleri i├žin) ortaya ├ž─▒kt─▒. T├╝m se├ženeklerin ve tekniklerin ne oldu─čunu anlamak ├Ânemsiz bir mesele de─čildi, bu y├╝zden sonu├žlar─▒ ayn─▒ ara┼čt─▒rmalar─▒n s─▒k─▒nt─▒s─▒ndan kurtarmak i├žin Stack Overflow okuyucular─▒ ile payla┼čmak i├žin bu topluluk wiki giri┼čini olu┼čturman─▒n tedbirli oldu─čunu d├╝┼č├╝nd├╝m.

Deney: Genel anlamda performans ipu├žlar─▒ndan bahsetmek yerine (yani, "Bir i┼člem kullan─▒n!" ), Baz─▒ C kodlar─▒ yazman─▒n ve ├že┼čitli se├ženeklerin etkisini ├Âl├žmenin en iyi yolu oldu─čunu d├╝┼č├╝nd├╝m . Baz─▒ basit verilerle ba┼člayaca─č─▒z:

  • Toronto ┼čehri i├žin 28 MB'l─▒k bir TAB ile ayr─▒lm─▒┼č metin dosyas─▒ (yakla┼č─▒k 865.000 kay─▒t)http://www.toronto.ca/open/datasets/ttc-routes
  • Test makinem, Windows XP ├žal─▒┼čt─▒ran 3.60 GHz P4.
  • Kod, Visual C ++ 2005 ile birlikte "Tam Optimizasyon" (/ Ox) ve Favor H─▒zl─▒ Kod (/ Ot) ile "Release" olarak derlenir .
  • Do─črudan test uygulamamda derlenen SQLite "Amalgamation" program─▒n─▒ kullan─▒yorum. Sahip oldu─čum SQLite s├╝r├╝m├╝ biraz daha eski (3.6.7), ancak bu sonu├žlar─▒n en son s├╝r├╝mle kar┼č─▒la┼čt─▒r─▒labilir olaca─č─▒ndan ┼č├╝pheliyim (l├╝tfen ba┼čka bir ┼čey d├╝┼č├╝n├╝rseniz yorum b─▒rak).

Biraz kod yazal─▒m!

Kod: Metin dosyas─▒n─▒ sat─▒r sat─▒r okuyan, dizeyi de─čerlere b├Âlen ve ard─▒ndan verileri bir SQLite veritaban─▒na ekleyen basit bir C program─▒. Kodun bu "temel" s├╝r├╝m├╝nde, veritaban─▒ olu┼čturulur, ancak ger├žekte veri eklemeyece─čiz:

 /*************************************************************
    Baseline code to experiment with SQLite performance.

    Input data is a 28 MB TAB-delimited text file of the
    complete Toronto Transit System schedule/route info
    from http://www.toronto.ca/open/datasets/ttc-routes/

**************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "sqlite3.h"

#define INPUTDATA "C:\\TTC_schedule_scheduleitem_10-27-2009.txt"
#define DATABASE "c:\\TTC_schedule_scheduleitem_10-27-2009.sqlite"
#define TABLE "CREATE TABLE IF NOT EXISTS TTC (id INTEGER PRIMARY KEY, Route_ID TEXT, Branch_Code TEXT, Version INTEGER, Stop INTEGER, Vehicle_Index INTEGER, Day Integer, Time TEXT)"
#define BUFFER_SIZE 256

int main(int argc, char **argv) {

    sqlite3 * db;
    sqlite3_stmt * stmt;
    char * sErrMsg = 0;
    char * tail = 0;
    int nRetCode;
    int n = 0;

    clock_t cStartClock;

    FILE * pFile;
    char sInputBuf [BUFFER_SIZE] = "\0";

    char * sRT = 0;  /* Route */
    char * sBR = 0;  /* Branch */
    char * sVR = 0;  /* Version */
    char * sST = 0;  /* Stop Number */
    char * sVI = 0;  /* Vehicle */
    char * sDT = 0;  /* Date */
    char * sTM = 0;  /* Time */

    char sSQL [BUFFER_SIZE] = "\0";

    /*********************************************/
    /* Open the Database and create the Schema */
    sqlite3_open(DATABASE, &db);
    sqlite3_exec(db, TABLE, NULL, NULL, &sErrMsg);

    /*********************************************/
    /* Open input file and import into Database*/
    cStartClock = clock();

    pFile = fopen (INPUTDATA,"r");
    while (!feof(pFile)) {

        fgets (sInputBuf, BUFFER_SIZE, pFile);

        sRT = strtok (sInputBuf, "\t");     /* Get Route */
        sBR = strtok (NULL, "\t");            /* Get Branch */
        sVR = strtok (NULL, "\t");            /* Get Version */
        sST = strtok (NULL, "\t");            /* Get Stop Number */
        sVI = strtok (NULL, "\t");            /* Get Vehicle */
        sDT = strtok (NULL, "\t");            /* Get Date */
        sTM = strtok (NULL, "\t");            /* Get Time */

        /* ACTUAL INSERT WILL GO HERE */

        n++;
    }
    fclose (pFile);

    printf("Imported %d records in %4.2f seconds\n", n, (clock() - cStartClock) / (double)CLOCKS_PER_SEC);

    sqlite3_close(db);
    return 0;
}
 

Kontrol"

Kodun oldu─ču gibi ├žal─▒┼čt─▒r─▒lmas─▒ asl─▒nda herhangi bir veritaban─▒ i┼člemini ger├žekle┼čtirmez, ancak ham C dosyas─▒ G / ├ç ve dize i┼čleme i┼člemlerinin ne kadar h─▒zl─▒ oldu─ču hakk─▒nda bir fikir verecektir.

0,94 saniyede 864913 kay─▒t al─▒nd─▒

Harika! Ger├žekten herhangi bir ek yapmamak kayd─▒yla saniyede 920.000 ek yapabiliriz :-)


"En K├Ât├╝ Durum-Senaryosu"

Dosyadan okunan de─čerleri kullanarak SQL dizesini olu┼čturaca─č─▒z ve sqlite3_exec kullanarak bu SQL i┼člemini ├ža─č─▒raca─č─▒z:

 sprintf(sSQL, "INSERT INTO TTC VALUES (NULL, '%s', '%s', '%s', '%s', '%s', '%s', '%s')", sRT, sBR, sVR, sST, sVI, sDT, sTM);
sqlite3_exec(db, sSQL, NULL, NULL, &sErrMsg);
 

Bu yava┼člayacakt─▒r ├ž├╝nk├╝ her yaz─▒ i├žin SQL VDBE kodunda derlenecek ve her yaz─▒ kendi i┼čleminde ger├žekle┼čecektir. Ne kadar yava┼č?

9933.61 saniyede 864913 kay─▒t al─▒nd─▒

Olmad─▒! 2 saat 45 dakika! Bu saniyede sadece 85 ekler.

─░┼člem Kullan─▒m─▒

Varsay─▒lan olarak, SQLite her INSERT / UPDATE deyimini benzersiz bir i┼člem i├žinde de─čerlendirir. ├çok say─▒da kesici u├ž kullan─▒yorsan─▒z, i┼čleminizi bir i┼čleme koyman─▒z ├Ânerilir:

 sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);

pFile = fopen (INPUTDATA,"r");
while (!feof(pFile)) {

    ...

}
fclose (pFile);

sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &sErrMsg);
 

38.03 saniyede 864913 kay─▒t al─▒nd─▒

Bu daha iyi. T├╝m u├žlar─▒m─▒z─▒ tek bir i┼člemle basit├že sarmak, performans─▒m─▒z─▒ saniyede 23.000 u├žlara ├ž─▒kard─▒ .

Haz─▒rlanan Bir Bildirim Kullanma

Bir i┼člem kullanmak ├žok b├╝y├╝k bir geli┼čmeydi, ancak ayn─▒ SQL'i tekrar tekrar kullan─▒yorsak, her bir ek i├žin SQL deyimini yeniden derlemek mant─▒kl─▒ gelmiyor. sqlite3_prepare_v2 SQL ifademizi bir kez derlemek i├žin kullanal─▒m ve sonra parametrelerimizi kullanarak sqlite3_bind_text a┼ča─č─▒daki ifadeyi ba─člayal─▒m :

 /* Open input file and import into the database */
cStartClock = clock();

sprintf(sSQL, "INSERT INTO TTC VALUES (NULL, @RT, @BR, @VR, @ST, @VI, @DT, @TM)");
sqlite3_prepare_v2(db,  sSQL, BUFFER_SIZE, &stmt, &tail);

sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);

pFile = fopen (INPUTDATA,"r");
while (!feof(pFile)) {

    fgets (sInputBuf, BUFFER_SIZE, pFile);

    sRT = strtok (sInputBuf, "\t");   /* Get Route */
    sBR = strtok (NULL, "\t");        /* Get Branch */
    sVR = strtok (NULL, "\t");        /* Get Version */
    sST = strtok (NULL, "\t");        /* Get Stop Number */
    sVI = strtok (NULL, "\t");        /* Get Vehicle */
    sDT = strtok (NULL, "\t");        /* Get Date */
    sTM = strtok (NULL, "\t");        /* Get Time */

    sqlite3_bind_text(stmt, 1, sRT, -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 2, sBR, -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 3, sVR, -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 4, sST, -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 5, sVI, -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 6, sDT, -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(stmt, 7, sTM, -1, SQLITE_TRANSIENT);

    sqlite3_step(stmt);

    sqlite3_clear_bindings(stmt);
    sqlite3_reset(stmt);

    n++;
}
fclose (pFile);

sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &sErrMsg);

printf("Imported %d records in %4.2f seconds\n", n, (clock() - cStartClock) / (double)CLOCKS_PER_SEC);

sqlite3_finalize(stmt);
sqlite3_close(db);

return 0;
 

Al─▒nan 864913 kay─▒t 16.27 saniyede

G├╝zel! Biraz daha fazla kod var (aramay─▒ sqlite3_clear_bindings ve aramay─▒ unutmay─▒n sqlite3_reset ), ancak performans─▒m─▒z─▒ saniyede 53.000 eke iki kat─▒na ├ž─▒kard─▒k.

PRAGMA senkron = KAPALI

Varsay─▒lan olarak, SQLite i┼čletim sistemi d├╝zeyinde bir yazma komutu verdikten sonra duraklar. Bu, verilerin diske yaz─▒ld─▒─č─▒n─▒ garanti eder. Ayar─▒na g├Âre synchronous = OFF , devam sonra yaz─▒p i├žin basit├že el-off OS verilere SQLite talimat verirsiniz. Veri tablas─▒na yaz─▒lmadan ├Ânce, bilgisayar feci bir ├ž├Âkmeye maruz kal─▒rsa (veya elektrik kesintisi) veritaban─▒ dosyas─▒n─▒n bozulma olas─▒l─▒─č─▒ vard─▒r:

 /* Open the database and create the schema */
sqlite3_open(DATABASE, &db);
sqlite3_exec(db, TABLE, NULL, NULL, &sErrMsg);
sqlite3_exec(db, "PRAGMA synchronous = OFF", NULL, NULL, &sErrMsg);
 

Al─▒nan 864913 kay─▒t, 12.41 saniyede

Geli┼čmeler ┼čimdi daha k├╝├ž├╝k, ancak saniyede 69.600 eke kadar var─▒z.

PRAGMA journal_mode = MEMORY

De─čerlendirerek geri alma g├╝nl├╝─č├╝n├╝ belle─če kaydetmeyi d├╝┼č├╝n├╝n PRAGMA journal_mode = MEMORY . ─░┼čleminiz daha h─▒zl─▒ olacakt─▒r, ancak i┼čleminizi kaybederseniz veya bir i┼člem s─▒ras─▒nda program─▒n─▒z ├ž├Âkerse, veritaban─▒ k─▒smen tamamlanm─▒┼č bir i┼člemle bozuk bir durumda kalabilir:

 /* Open the database and create the schema */
sqlite3_open(DATABASE, &db);
sqlite3_exec(db, TABLE, NULL, NULL, &sErrMsg);
sqlite3_exec(db, "PRAGMA journal_mode = MEMORY", NULL, NULL, &sErrMsg);
 

13.50 saniyede 864913 kay─▒t al─▒nd─▒

Saniyede 64.000 u├žta ├Ânceki optimizasyondan biraz daha yava┼č .

PRAGMA senkron = KAPALI ve PRAGMA journal_mode = MEMORY

├ľnceki iki optimizasyonu birle┼čtirelim. Biraz daha riskli (├ž├Âkme durumunda), ancak yaln─▒zca veri al─▒yoruz (bir banka ├žal─▒┼čt─▒rm─▒yoruz):

 /* Open the database and create the schema */
sqlite3_open(DATABASE, &db);
sqlite3_exec(db, TABLE, NULL, NULL, &sErrMsg);
sqlite3_exec(db, "PRAGMA synchronous = OFF", NULL, NULL, &sErrMsg);
sqlite3_exec(db, "PRAGMA journal_mode = MEMORY", NULL, NULL, &sErrMsg);
 

Al─▒nan 864913 kay─▒t 12.00 saniyede

Fantastik! Saniyede 72.000 ek yapabiliriz .

Bellek ─░├ži Veritaban─▒n─▒ Kullanma

Sadece tekmeler i├žin, ├Ânceki t├╝m optimizasyonlar─▒ olu┼čtural─▒m ve veritaban─▒ dosya ad─▒n─▒ yeniden tan─▒mlayal─▒m, b├Âylece tamamen RAM'de ├žal─▒┼č─▒yoruz:

 #define DATABASE ":memory:"
 

10.94 saniyede 864913 kay─▒t al─▒nd─▒

Veritaban─▒m─▒z─▒ RAM'de depolamak s├╝per pratik de─čildir, ancak saniyede 79.000 ekleyebilmemiz etkileyicidir .

Refactoring C Kodu

Her ne kadar ├Âzellikle bir SQLite iyile┼čtirmesi olmasa char* da, while d├Âng├╝deki fazladan atama i┼člemlerinden ho┼članm─▒yorum . Bu kodu strtok() do─črudan ├ž─▒kt─▒n─▒n i├žine aktarmak i├žin h─▒zla yeniden d├╝zenleyelim sqlite3_bind_text() ve derleyicinin bizim i├žin i┼čleri h─▒zland─▒rmaya ├žal─▒┼čmas─▒na izin verelim:

 pFile = fopen (INPUTDATA,"r");
while (!feof(pFile)) {

    fgets (sInputBuf, BUFFER_SIZE, pFile);

    sqlite3_bind_text(stmt, 1, strtok (sInputBuf, "\t"), -1, SQLITE_TRANSIENT); /* Get Route */
    sqlite3_bind_text(stmt, 2, strtok (NULL, "\t"), -1, SQLITE_TRANSIENT);    /* Get Branch */
    sqlite3_bind_text(stmt, 3, strtok (NULL, "\t"), -1, SQLITE_TRANSIENT);    /* Get Version */
    sqlite3_bind_text(stmt, 4, strtok (NULL, "\t"), -1, SQLITE_TRANSIENT);    /* Get Stop Number */
    sqlite3_bind_text(stmt, 5, strtok (NULL, "\t"), -1, SQLITE_TRANSIENT);    /* Get Vehicle */
    sqlite3_bind_text(stmt, 6, strtok (NULL, "\t"), -1, SQLITE_TRANSIENT);    /* Get Date */
    sqlite3_bind_text(stmt, 7, strtok (NULL, "\t"), -1, SQLITE_TRANSIENT);    /* Get Time */

    sqlite3_step(stmt);        /* Execute the SQL Statement */
    sqlite3_clear_bindings(stmt);    /* Clear bindings */
    sqlite3_reset(stmt);        /* Reset VDBE */

    n++;
}
fclose (pFile);
 

Not: Ger├žek bir veritaban─▒ dosyas─▒ kullanmaya geri d├Ând├╝k. Bellek i├ži veritabanlar─▒ h─▒zl─▒d─▒r ancak zorunlu olarak pratik de─čildir

8.94 saniyede 864913 kay─▒t al─▒nd─▒

Parametre ba─člant─▒m─▒zda kullan─▒lan string i┼čleme koduna hafif bir yeniden d├╝zenleme, saniyede 96.700 kesici u├ž eklememize izin verdi . Bunun ├žok h─▒zl─▒ oldu─čunu s├Âylemenin g├╝venli oldu─čunu d├╝┼č├╝n├╝yorum . Di─čer de─či┼čkenleri (├Ârne─čin sayfa boyutu, dizin olu┼čturma vb.) Ayarlamaya ba┼člad─▒─č─▒m─▒zda, bu bizim ├Âl├ž├╝t├╝m├╝z olacakt─▒r.


├ľzet (┼čimdiye kadar)

Umar─▒m hala benimlesin! Bu yolda ba┼člamam─▒z─▒n nedeni toplu ekleme performans─▒n─▒n SQLite ile ├žok ├ž─▒lg─▒nca de─či┼čmesi ve operasyonumuzu h─▒zland─▒rmak i├žin ne gibi de─či┼čiklikler yap─▒lmas─▒ gerekti─či her zaman a├ž─▒k de─čil. Ayn─▒ derleyiciyi (ve derleyici se├ženeklerini), ayn─▒ SQLite s├╝r├╝m├╝n├╝ ve ayn─▒ verileri kullanarak kodumuzu ve SQLite kullan─▒m─▒m─▒z─▒ saniyede 85 kesici u├ž senaryosundan saniyede 96,000 eklemeye kadar optimize etmek i├žin optimize ettik !


INDEX CREATE sonra INSERT vs. INSERT CREATE sonra INDEX CREATE

SELECT Performans─▒ ├Âl├žmeye ba┼člamadan ├Ânce , endeks olu┼čturaca─č─▒m─▒z─▒ biliyoruz. A┼ča─č─▒daki cevaplardan birinde, toplu ekler yaparken, verilerin eklenmesinden sonra dizini olu┼čturman─▒n daha h─▒zl─▒ oldu─ču ├Ânerilmi┼čtir (ilk ├Ânce dizini olu┼čturman─▒n ard─▒ndan verileri eklerken). Hadi deneyelim:

Dizin Olu┼čtur sonra Veri Ekle

 sqlite3_exec(db, "CREATE  INDEX 'TTC_Stop_Index' ON 'TTC' ('Stop')", NULL, NULL, &sErrMsg);
sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
...
 

18.13 saniyede 864913 kay─▒t al─▒nd─▒

Veri Ekle sonra Dizin Olu┼čtur

 ...
sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &sErrMsg);
sqlite3_exec(db, "CREATE  INDEX 'TTC_Stop_Index' ON 'TTC' ('Stop')", NULL, NULL, &sErrMsg);
 

13.66 saniyede 864913 kay─▒t al─▒nd─▒

Beklendi─či gibi, bir s├╝tun dizine eklenmi┼čse toplu eklemeler daha yava┼čt─▒r, ancak veriler eklendikten sonra dizinin olu┼čturulmu┼č olmas─▒ bir fark yarat─▒r. Endeks i├žermeyen taban ├žizgimiz, saniyede 96.000 u├žtur. ├ľnce dizini olu┼čturmak, ard─▒ndan veri eklemek bize saniyede 47.700 ek sa─člar, oysa ├Ânce verileri yerle┼čtirmek sonra dizini olu┼čturmak bize saniyede 63.300 ek sa─člar.


Memnuniyetle denemek i├žin di─čer senaryolar i├žin ├Âneride bulunmak isterim ... Ve yak─▒nda SELECT sorgular─▒ i├žin benzer verileri derleyece─čim.


2853









Cevap say─▒s─▒n─▒ say: 10






Birka├ž ipucu:

  1. Bir i┼čleme ekler / g├╝ncellemeler koyun.
  2. Daha eski SQLite s├╝r├╝mleri i├žin - Daha az paranoyak bir g├╝nl├╝k modu ( pragma journal_mode ) d├╝┼č├╝n├╝n . Var NORMAL ve sonra OFF , i┼čletim sistemi ├ž├Âkerse b├╝y├╝k olas─▒l─▒kla bozulacak kadar endi┼če duymuyorsan─▒z, ekleme h─▒z─▒n─▒ ├Ânemli ├Âl├ž├╝de art─▒rabilir. Uygulaman─▒z─▒n ├ž├Âkmesi durumunda verilerin iyi olmas─▒ gerekir. Yeni s├╝r├╝mlerde, OFF/MEMORY ayarlar─▒n uygulama d├╝zeyinde ├ž├Âkmeler i├žin g├╝venli olmad─▒─č─▒n─▒ unutmay─▒n.
  3. Sayfa boyutlar─▒yla oynamak da bir fark yarat─▒r ( PRAGMA page_size ). Daha b├╝y├╝k sayfa boyutlar─▒na sahip olmak, daha b├╝y├╝k sayfalar bellekte tutuldu─ču i├žin okuma ve yazma i┼člemlerinin biraz daha h─▒zl─▒ ge├žmesini sa─člayabilir. Veritaban─▒n─▒z i├žin daha fazla bellek kullan─▒laca─č─▒n─▒ unutmay─▒n.
  4. Endeksleriniz varsa, CREATE INDEX t├╝m eklerinizi yapt─▒ktan sonra aramay─▒ d├╝┼č├╝n├╝n . Bu, dizini olu┼čturup eklerinizi yapmaktan ├žok daha h─▒zl─▒d─▒r.
  5. Yazma i┼člemi tamamland─▒─č─▒nda t├╝m veritaban─▒ kilitlendi─činden ve birden fazla okuyucu m├╝mk├╝n olsa da, yazma i┼člemleri kilitlenece─činden, SQLite'ye ayn─▒ anda eri┼čiminiz varsa olduk├ža dikkatli olmal─▒s─▒n─▒z. Bu, daha yeni SQLite s├╝r├╝mlerinde bir WAL ilavesiyle biraz geli┼čtirildi.
  6. Yerden tasarruf etmenin avantajlar─▒ndan yararlan─▒n ... k├╝├ž├╝k veritabanlar─▒ daha h─▒zl─▒ gidiyor. ├ľrne─čin, anahtar de─čer ├žiftleriniz INTEGER PRIMARY KEY varsa , anahtar─▒ tablodaki ima edilen benzersiz sat─▒r numaras─▒ s├╝tununun yerine ge├žecek ┼čekilde m├╝mk├╝n k─▒lmay─▒ deneyin .
  7. Birden fazla i┼č par├žac─▒─č─▒ kullan─▒yorsan─▒z, y├╝klenen sayfalar─▒n i┼č par├žac─▒─č─▒ aras─▒nda payla┼č─▒lmas─▒n─▒ ve pahal─▒ G / ├ç ├ža─čr─▒lar─▒n─▒ engelleyebilecek payla┼č─▒lan sayfa ├Ânbelle─čini kullanmay─▒ deneyebilirsiniz .
  8. Kullanma !feof(file) !

Ayr─▒ca burada ve burada benzer sorular sordum .


747







Bu ekler i├žin SQLITE_STATIC yerine kullanmay─▒ deneyin SQLITE_TRANSIENT .

SQLITE_TRANSIENT SQLite, d├Ând├╝rmeden ├Ânce string verilerini kopyalamas─▒na neden olacakt─▒r.

SQLITE_STATIC Verdi─činiz haf─▒za adresinin sorgu yap─▒l─▒ncaya kadar ge├žerli olaca─č─▒n─▒ s├Âyler (ki bu d├Âng├╝ her zaman b├Âyledir). Bu, d├Âng├╝ ba┼č─▒na birka├ž ay─▒rma, kopyalama ve kald─▒rma i┼čleminden tasarruf etmenizi sa─člar. Muhtemelen b├╝y├╝k bir geli┼čme.


130







Ka├ž─▒n─▒n sqlite3_clear_bindings(stmt) .

Testteki kod, her seferinde yeterli olmas─▒ gereken ba─člamalar─▒ ayarlar.

C API intro SQLite dok├╝manlardan diyor ki:

Sqlite3_step () i┼člevini ilk kez ├ža─č─▒rmadan ├Ânce veya sqlite3_reset () i┼člevinden hemen sonra uygulama , parametrelere de─čer eklemek i├žin sqlite3_bind () arabirimlerini ├žal─▒┼čt─▒rabilir. Sqlite3_bind () ├Â─česine yap─▒lan her ├ža─čr─▒ , ayn─▒ parametrede bulunan ├Ânceki ba─člant─▒lar─▒ ge├žersiz k─▒lar

Dok├╝manlarda sqlite3_clear_bindings , ciltleri basit bir ┼čekilde ayarlamaya ek olarak araman─▒z gerekti─čini s├Âyleyen hi├žbir ┼čey yoktur .

Daha fazla ayr─▒nt─▒: Avoid_sqlite3_clear_bindings ()


97







Toplu eklerde

Bu mesajdan ve beni buraya y├Ânlendiren Y─▒─č─▒n Ta┼čmas─▒ sorusundan esinlenildi - Bir SQLite veritaban─▒na bir defada birden fazla sat─▒r eklemek m├╝mk├╝n m├╝d├╝r? - ─░lk Git depomu yay─▒nlad─▒m :

https://github.com/rdpoor/CreateOrUpdate

hangi bir ActiveRecords dizisini MySQL , SQLite veya PostgreSQL veritabanlar─▒na y├╝kler . Mevcut kay─▒tlar─▒ yok saymak, ├╝zerine yazmak veya bir hata bildirmek i├žin bir se├ženek i├žerir. ─░lkel kriterlerim s─▒ral─▒ yazmalara k─▒yasla 10 kat daha h─▒zl─▒ bir geli┼čme g├Âsteriyor - YMMV.

S─▒k s─▒k b├╝y├╝k veri k├╝melerini i├že aktarmam gereken ├╝retim kodunda kullan─▒yorum ve bundan ├žok mutluyum.


59







INSERT / UPDATE ifadelerinizi y─▒─č─▒nland─▒rabilirseniz, toplu i├že aktarma en iyi ┼čekilde g├Âr├╝n├╝yor . 10.000 de─čerinde bir de─čer, benim i├žin sadece birka├ž sat─▒r olan bir masada, YMMV ...


48







Yaln─▒zca okumay─▒ umursuyorsan─▒z, biraz daha h─▒zl─▒ (ancak eski verileri okuyabilir) s├╝r├╝m, birden fazla i┼č par├žac─▒─č─▒ndan (i┼č par├žac─▒─č─▒ ba┼č─▒na ba─člant─▒) birden ├žok ba─člant─▒dan okumakt─▒r.

├ľncelikle tablodaki maddeleri bulun:

 SELECT COUNT(*) FROM table
 

sonra sayfalar─▒ okuyunuz (LIMIT / OFFSET):

 SELECT * FROM table ORDER BY _ROWID_ LIMIT <limit> OFFSET <offset>
 

konu ba┼č─▒na nerede ve hesaplan─▒r, ┼č├Âyle:

 int limit = (count + n_threads - 1)/n_threads;
 

her konu i├žin:

 int offset = thread_index * limit
 

K├╝├ž├╝k (200 MB) db i├žin bu% 50-75 h─▒zland─▒ (Windows 7'de 3.8.0.2 64-bit). Tablolar─▒m─▒z a─č─▒r normalle┼čmedi (1000-1500 s├╝tun, kabaca 100.000 veya daha fazla sat─▒r).

├çok az veya ├žok az say─▒da iplik bunu yapmaz, kendinizi kar┼č─▒la┼čt─▒rman─▒z ve kendiniz profillemeniz gerekir.

Ayr─▒ca bizim i├žin, SHAREDCACHE performans─▒ yava┼člatt─▒, bu y├╝zden manuel olarak PRIVATECACHE'i koydum (├ž├╝nk├╝ bizim i├žin k├╝resel olarak etkinle┼čtirildi)


42







Cache_size de─čerini daha y├╝ksek bir de─čere y├╝kseltti─čime kadar i┼člemlerden herhangi bir kazan├ž elde edemedim. PRAGMA cache_size=10000;


29







Bu dersi okuduktan sonra program─▒ma uygulamaya ├žal─▒┼čt─▒m.

Adres i├žeren 4-5 dosyam var. Her dosyan─▒n yakla┼č─▒k 30 milyon kayd─▒ vard─▒r. ├ľnerdi─činiz ayn─▒ yap─▒land─▒rmay─▒ kullan─▒yorum, ancak saniye ba┼č─▒na INSERT'lerin say─▒s─▒ ├žok d├╝┼č├╝k (saniyede ~ 10.000 kay─▒t).

├ľnerin burada ba┼čar─▒s─▒z. T├╝m kay─▒tlar i├žin tek bir i┼člem ve hatas─▒z / ba┼čar─▒s─▒z olan tek bir ek kullan─▒yorsunuz. Diyelim ki her bir kayd─▒ farkl─▒ tablolardaki birden fazla eke ay─▒r─▒yorsunuz. Kay─▒t bozulursa ne olur?

ON CONFLICT komutu ge├žerli de─čildir, ├ž├╝nk├╝ bir kay─▒tta 10 eleman varsa ve e─čer eleman 5 bir CONSTRAINT hatas─▒ al─▒rsa, ├Ânceki t├╝m 4 kesici u├ž da gitmelidir.

─░┼čte geri d├Ân├╝┼č├╝n oldu─ču yer buras─▒. Geri alma ile ilgili tek sorun, t├╝m u├žlar─▒n─▒z─▒ kaybetmeniz ve en ba┼čtan ba┼člaman─▒zd─▒r. Bunu nas─▒l ├ž├Âzebilirsiniz?

Benim ├ž├Âz├╝m├╝m birden fazla i┼člem kullanmakt─▒ . Her 10.000 kay─▒tta bir i┼člem ba┼člat─▒yorum ve sonland─▒r─▒yorum (Bu numaray─▒ neden test etti─čimin en h─▒zl─▒s─▒yd─▒? 10.000 boyutunda bir dizi olu┼čturdum ve ba┼čar─▒l─▒ kay─▒tlar─▒ oraya ekledim. Hata olu┼čtu─čunda, bir geri alma i┼člemi yap─▒yorum, bir i┼čleme ba┼člad─▒m, dizimdeki kay─▒tlar─▒ ekliyorum, taahh├╝t ediyorum ve sonra da k─▒r─▒lan kay─▒ttan sonra yeni bir i┼čleme ba┼člad─▒m.

Bu ├ž├Âz├╝m, hatal─▒ / yinelenen kay─▒tlar─▒ i├žeren dosyalarla u─čra┼č─▒rken kar┼č─▒la┼čt─▒─č─▒m sorunlar─▒ atlamama yard─▒mc─▒ oldu (neredeyse% 4'├╝nde k├Ât├╝ kay─▒t vard─▒).

Olu┼čturdu─čum algoritma, i┼člemimi 2 saat d├╝┼č├╝rmeme yard─▒mc─▒ oldu. Dosya 1hr 30m'nin son y├╝kleme i┼člemi hala yava┼č fakat ba┼člang─▒├žta ald─▒─č─▒ 4 saat ile kar┼č─▒la┼čt─▒r─▒lmad─▒. Ekleri 10.000 / s'den ~ 14.000 / s'ye kadar h─▒zland─▒rmay─▒ ba┼čard─▒m

Herhangi birisinin nas─▒l h─▒zland─▒r─▒laca─č─▒ konusunda ba┼čka bir fikri varsa, ├Ânerilere a├ž─▒─č─▒m.

G├ťNCELLEME :

Yukar─▒daki cevaba ek olarak, kulland─▒─č─▒n─▒z sabit s├╝r├╝c├╝ye ba─čl─▒ olarak saniyede bir u├ž koydu─čunu da akl─▒n─▒zda tutmal─▒s─▒n─▒z. Farkl─▒ sabit disklere sahip 3 farkl─▒ bilgisayarda test ettim ve zaman zaman ├žok b├╝y├╝k farklar g├Ârd├╝m. PC1 (1 saat 30m), PC2 (6 saat) PC3 (14 saat), bu y├╝zden bunun neden olaca─č─▒n─▒ merak etmeye ba┼člad─▒m.

─░ki haftal─▒k ara┼čt─▒rma ve ├žoklu kaynaklar─▒ kontrol ettikten sonra: Sabit S├╝r├╝c├╝, Ram, ├ľnbellek, sabit s├╝r├╝c├╝n├╝zdeki baz─▒ ayarlar─▒n G / ├ç oran─▒n─▒ etkileyebilece─čini ├Â─črendim. ─░stedi─činiz ├ž─▒k─▒┼č s├╝r├╝c├╝deki ├Âzellikleri t─▒klatarak genel sekmede iki se├ženek g├Ârebilirsiniz. Opt1: Bu s├╝r├╝c├╝y├╝ s─▒k─▒┼čt─▒r, Opt2: Bu s├╝r├╝c├╝n├╝n dosyalar─▒n─▒n i├žerik dizine eklenmesine izin ver.

Bu iki se├žene─čin devre d─▒┼č─▒ b─▒rak─▒lmas─▒yla, 3 PC'nin hepsi de bitmek ├╝zere yakla┼č─▒k ayn─▒ zaman al─▒r (1 saat ve 20 ila 40 dakika). Yava┼č u├žlar ile kar┼č─▒la┼č─▒rsan─▒z, sabit s├╝r├╝c├╝n├╝z├╝n bu se├ženeklerle yap─▒land─▒r─▒lm─▒┼č olup olmad─▒─č─▒n─▒ kontrol edin. Size ├ž├Âz├╝m bulmaya ├žal─▒┼č─▒rken size ├žok zaman kazand─▒racak ve ba┼č a─čr─▒lar─▒ yaratacakt─▒r.


20







Sorunuzun cevab─▒, daha yeni sqlite3'├╝n performans─▒ art─▒rd─▒─č─▒, bunu kullan─▒n.

Bu cevap Neden sqlite ile SQLAlchemy insert do─črudan sqlite3 kullanmaktan 25 kat daha yava┼č? SqlAlchemy Orm Yazar taraf─▒ndan 0,5 saniyede 100k ekler vard─▒r ve ben python-sqlite ve SqlAlchemy ile benzer sonu├žlar g├Ârd├╝m. Bu da sqlite3 ile performans─▒n artt─▒─č─▒na inanmam─▒ sa─čl─▒yor


11







Toplu verileri db'ye eklemek i├žin ContentProvider'─▒ kullan─▒n. Veriyi veritaban─▒na toplu veri eklemek i├žin kullan─▒lan a┼ča─č─▒daki y├Ântem. Bu, SQLite'─▒n saniyede INSERT performans─▒n─▒ geli┼čtirmelidir.

 private SQLiteDatabase database;
database = dbHelper.getWritableDatabase();

public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {

database.beginTransaction();

for (ContentValues value : values)
 db.insert("TABLE_NAME", null, value);

database.setTransactionSuccessful();
database.endTransaction();

}
 

BulkInsert y├Ântemini ├ža─č─▒r─▒n:

 App.getAppContext().getContentResolver().bulkInsert(contentUriTable,
            contentValuesArray);
 

Ba─člant─▒: https://www.vogella.com/tutorials/AndroidSQLite/article.html daha fazla ayr─▒nt─▒ i├žin ContentProvider B├Âl├╝m├╝n├╝ Kullanarak kontrol edin


-1