2009-11-09 11 views
26

मैंने सुना है कि SQLite साथ तैयार बयानों प्रदर्शन में सुधार आएगा। मैंने परीक्षण करने के लिए कुछ कोड लिखा, और उन्हें उपयोग करने में प्रदर्शन में कोई अंतर नहीं देखा। तो, मैंने सोचा कि शायद मेरा कोड गलत था। कृपया query optimizer के बाद execution plan for a query कैशिंग सबसे अच्छा योजना में पाया गया है द्वारा मुझे पता है अगर तुम मुझे यह कैसे कर रहा हूँ में किसी भी त्रुटि देखते हैं ...SQLite में, तैयार कथन वास्तव में प्रदर्शन में सुधार करते हैं?

[self testPrep:NO dbConn:dbConn]; 
[self testPrep:YES dbConn:dbConn]; 

reuse=0 
recs=2000 
2009-11-09 10:39:18 -0800 
processing... 
2009-11-09 10:39:32 -0800 

reuse=1 
recs=2000 
2009-11-09 10:39:32 -0800 
processing... 
2009-11-09 10:39:46 -0800 

-(void)testPrep:(BOOL)reuse dbConn:(sqlite3*)dbConn{ 
    int recs = 2000; 
    NSString *sql; 
    sqlite3_stmt *stmt; 

    sql = @"DROP TABLE test"; 
    sqlite3_exec(dbConn, [sql UTF8String],NULL,NULL,NULL); 

    sql = @"CREATE TABLE test (id INT,field1 INT, field2 INT,field3 INT,field4 INT,field5 INT,field6 INT,field7 INT,field8 INT,field9 INT,field10 INT)"; 
    sqlite3_exec(dbConn, [sql UTF8String],NULL,NULL,NULL); 

    for(int i=0;i<recs;i++){ 
     sql = @"INSERT INTO test (id,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10) VALUES (%d,1,2,3,4,5,6,7,8,9,10)"; 
     sqlite3_exec(dbConn, [sql UTF8String],NULL,NULL,NULL); 
    } 

    sql = @"BEGIN"; 
    sqlite3_exec(dbConn, [sql UTF8String],NULL,NULL,NULL); 

    if (reuse){ 
     sql = @"select * from test where field1=?1 and field2=?2 and field3=?3 and field4=?4 and field5=?5 and field6=?6 and field6=?6 and field8=?8 and field9=?9 and field10=?10 and id=?11"; 
     sqlite3_prepare_v2(dbConn, [sql UTF8String], -1, &stmt, NULL); 
    } 

    NSLog(@"reuse=%d",reuse); 
    NSLog(@"recs=%d",recs); 
    NSDate *before = [NSDate date]; 
    NSLog([before description]); 
    NSLog(@"processing..."); 
    for(int i=0;i<recs;i++){ 
     if (!reuse){ 
      sql = @"select * from test where field1=?1 and field2=?2 and field3=?3 and field4=?4 and field5=?5 and field6=?6 and field6=?6 and field8=?8 and field9=?9 and field10=?10 and id=?11"; 
      sqlite3_prepare_v2(dbConn, [sql UTF8String], -1, &stmt, NULL); 
     } 
     sqlite3_bind_int(stmt, 1, 1); 
     sqlite3_bind_int(stmt, 2, 2); 
     sqlite3_bind_int(stmt, 3, 3); 
     sqlite3_bind_int(stmt, 4, 4); 
     sqlite3_bind_int(stmt, 5, 5); 
     sqlite3_bind_int(stmt, 6, 6); 
     sqlite3_bind_int(stmt, 7, 7); 
     sqlite3_bind_int(stmt, 8, 8); 
     sqlite3_bind_int(stmt, 9, 9); 
     sqlite3_bind_int(stmt, 10, 10); 
     sqlite3_bind_int(stmt, 11, i); 

     while(sqlite3_step(stmt) == SQLITE_ROW) { 
     } 
     sqlite3_reset(stmt); 
    } 

    sql = @"BEGIN"; 
    sqlite3_exec(dbConn, [sql UTF8String],NULL,NULL,NULL); 

    NSDate *after = [NSDate date]; 
    NSLog([after description]); 
} 
+0

यहां कुछ मीट्रिक (उस और अन्य गति सुधारों पर) हैं: http://stackoverflow.com/questions/1711631/improve-insert-per-second-performance-of-sqlite – cyrilchampier

उत्तर

19

तैयार बयान के प्रदर्शन में सुधार।

यदि आपके द्वारा उपयोग की जाने वाली क्वेरी में कोई जटिल योजना नहीं है (जैसे कि कोई भी शामिल नहीं होने के साथ सरल चयन/आवेषण), तो तैयार कथन आपको एक बड़ा सुधार नहीं देंगे क्योंकि ऑप्टिमाइज़र को सबसे अच्छी योजना मिल जाएगी ।

हालांकि, यदि आप एक क्वेरी के साथ एक ही परीक्षण चलाते हैं जिसमें कुछ शामिल होते हैं और कुछ इंडेक्स का उपयोग करते हैं, तो आप प्रदर्शन अंतर देखेंगे क्योंकि प्रत्येक बार क्वेरीज़र चलाने पर ऑप्टिमाइज़र नहीं चलाया जाएगा।

+3

इसके अलावा - शायद वहां * है * अधिक पुनरावृत्तियों के लिए एक अंतर दिखाई देता है। – Tomalak

+1

सरल प्रश्नों के लिए भी एक बड़ा अंतर है। मैंने गेम में प्रत्येक राज्य अपडेट के कई सरल आवेषण किए, यह ध्यान देने योग्य स्टटरिंग बनाम चिकनी चल रही थी। – Arahman

+0

@Omokoii आप वास्तव में खेल पाश सूत्र में डीबी संचालन दिखाने से बचना चाहिए ... – PSIXO

6

हां - यह विशाल अंतर बनाता है चाहे आप sqlite3_exec() बनाम sqlite3_prepare_v2()/sqlite3_bind_xxx()/sqlite3_step() थोक आवेषण के लिए उपयोग करते हैं।

sqlite3_exec() केवल एक सुविधा की विधि है। आंतरिक रूप से यह केवल sqlite3_prepare_v2() and sqlite3_step() के समान अनुक्रम को कॉल करता है। आपका उदाहरण कोड sqlite3_exec() बुला रहा है खत्म हो गया और इस पर एक शाब्दिक स्ट्रिंग पर:

for(int i=0;i<recs;i++){ 
    sql = @"INSERT INTO test (id,field1,field2,field3,field4,field5,field6,field7,field8,field9,field10) VALUES (%d,1,2,3,4,5,6,7,8,9,10)"; 
    sqlite3_exec(dbConn, [sql UTF8String],NULL,NULL,NULL); 
} 

मैं SQLite पार्सर की अंदरूनी कामकाज पता नहीं है, लेकिन शायद पार्सर बहुत चालाक पहचान करने के लिए है कि आप उपयोग कर रहे हैं एक ही शाब्दिक स्ट्रिंग और फिर प्रत्येक पुनरावृत्ति के साथ फिर से पार्सिंग/पुनः संकलन छोड़ देता है।

आप मूल्यों को बदलने के साथ ही प्रयोग की कोशिश - आप प्रदर्शन में एक बहुत बड़ा अंतर दिखाई देगा।

+0

मुझे लगता है कि यह एक अंतर की कि ज्यादा बना आश्चर्य हुआ। यह मेरे लिए एक बड़ी डालने से कुछ सेकंड दूर मुंडा, और मुझे बड़े आवेषण के लिए उम्मीद है। मैं अब बाँध कदम तैयार उपयोग करने के लिए सभी तरह की पूछताछ कन्वर्ट करने के लिए जा रहा हूँ। :) – Joe

-3

तैयार + कदम के बजाय निष्पादित विशाल प्रदर्शन में सुधार संभव हो रहे हैं का उपयोग करना। कुछ मामलों में प्रदर्शन लाभ निष्पादन समय में 100% से अधिक है।

+0

स्रोत और या मेट्रिक्स? – cyrilchampier

+0

हे, और 100% है कि बेतुका है असंभव है,। –

संबंधित मुद्दे