當前位置:成語大全網 - 書法字典 - 如何優化sqlite查詢

如何優化sqlite查詢

SQLite是典型的嵌入式數據庫管理系統。它有很多優點。它是輕量級的,編譯後非常小。原因之壹是在查詢優化上相對簡單。它只使用索引機制進行優化。在分析了SQLite的查詢優化並研究了源代碼之後,我把SQLite的查詢優化總結如下:

1.影響查詢性能的因素:

1.表格中的行數越少越好。

2.排序與否。

3.是否檢查壹個索引。

4.查詢語句的形式

二、幾種查詢優化的轉換

1.對於單個表的單個列,如果有T.C=expr形式的子句,並且都用OR運算符連接,比如:x = expr1或者expr2 = x或者x = expr3。此時,對於或,索引不能用於SQLite中的優化。所以可以在(expr1,expr2,expr3)中用IN運算符:x轉換成子句,這樣就可以用索引進行優化,效果很明顯,但如果沒有索引,or語句的執行效率會比IN語句稍好。

2.如果壹個子句的運算符是BETWEEN,那麽在SQLite中是無法通過index進行優化的,所以要進行相應的等價轉換。例如,b和c之間的a可以轉換為:(b和c之間的a)和(a & gt=b)和(a & lt=c).在上述條款中,(a & gt=b)和(a & lt=c)壹個被設置為dynamic且為(a BETWEEN b AND c)的子句,那麽如果BETWEEN語句已經被編碼,則該子句將被忽略,如果有可用的索引使該子句滿足條件,則父語句將被忽略。

3.如果壹個單元的運算符是LIKE,則進行如下轉換:x like' ABC% ',轉換為:x >;='abc '和x & ltabd .因為SQLite中的LIKE是無法通過索引進行優化的,如果有索引的話,遠談不上轉換和不轉換,因為它對LIKE不起作用,但是如果沒有索引,LIKE還是沒有轉換後那麽高效。

第三,幾個查詢語句的處理(復合查詢)

1.查詢語句是:< SelectA & gt& lt操作員& gt& lt選擇& gtORDER BY & ltorderbylist & gt以...排序

執行方法:是union all、union、except或intersect之壹。該語句的執行過程是先執行並排序selectA和selectB,然後掃描兩個結果。以上四種操作不同,執行過程分為七個子過程:

OutA:將selectA的壹行結果放入最終結果集中。

OutB:將selectA的壹行結果放入最終結果集中(最終結果集中只放入UNION操作和UNION ALL操作)。

AltB:當selectA的當前記錄小於selectB的當前記錄時。

AeqB:當selectA的當前記錄等於selectB的當前記錄時。

AgtB:selectA的當前記錄大於selectB的當前記錄時。

EofA:當selectA的結果被遍歷時。

EofB:當selectB的結果被遍歷時。

下面是四個操作的執行過程:

執行順序

聯合所有

聯盟

除...之外

橫斷

AltB:

outA,nextA

outA,nextA

outA,nextA

nextA

AeqB:

outA,nextA

nextA

nextA

outA,nextA

AgtB:

outB,nextB

outB,nextB

nextB

nextB

EofA:

outB,nextB

outB,nextB

停止

停止

EofB:

outA,nextA

outA,nextA

outA,nextA

停止

2.如果可能,可以將使用GROUP BY查詢的語句轉換為DISTINCT語句進行查詢,因為GROUP BY有時可能會使用index,但不會使用index for DISTINCT。

第四,子查詢扁平化

示例:選擇a from(選擇x+y作為a from t1其中z

壹般來說,執行這個SQL語句的默認方法是先執行內部查詢,把結果放到壹個臨時表中,然後在這個表上做壹個外部查詢,需要兩次數據處理。此外,這個臨時表沒有索引,因此無法優化外部查詢。如果處理上面的SQL,可以得到下面的SQL語句:select x+y as a from t 1其中z

查詢壹次數據就夠了,如果表t1上有索引,就避免遍歷整個表。

使用flatten方法優化SQL的條件:

1.子查詢和外部查詢都不使用集合函數。

2.子查詢沒有set函數,或者外部查詢不是表連接。

3.子查詢不是左外部聯接的右操作數。

4.子查詢不明確,或者外部查詢不是表連接。

5.子查詢不明確或外部查詢不是set函數。

6.子查詢沒有set函數,或者外部查詢沒有DISTINCT關鍵字。

7.子查詢有壹個FROM語句。

8.子查詢未使用LIMIT,或者外部查詢不是表連接。

9.子查詢不使用LIMIT,或者外部查詢不使用set函數。

10.子查詢沒有集合函數,或者外部查詢沒有限制。

11.子查詢和外部查詢不都是ORDER BY子句。

12.子查詢和外部查詢都不使用LIMIT。

13.子查詢中未使用偏移量

14.外部查詢不是復合查詢的壹部分,或者子查詢沒有同時使用關鍵字ORDER BY和LIMIT。

15.外部查詢沒有用。集合函數的子查詢不包含ORDER BY。

16.復合子查詢的扁平化:子查詢不是復合查詢,或者是UNION ALL復合查詢,但都是由幾個帶有非集合函數的查詢組成。他的父查詢不是復合查詢的子查詢,也不是set函數或DISTINCT查詢,並且FROM語句中沒有其他表或子查詢。父查詢和子查詢都可能包含WHERE語句,這將受到上述65438的影響。

示例:從(

從選項卡中選擇x

聯合所有

從選項卡中選擇y

聯合所有

從選項卡2中選擇abs(z*2)

)哪裏a!=5階乘1

轉換為:

從選項卡中選擇x+1,其中x+1!=5

聯合所有

從選項卡中選擇y+1,其中y+1!=5

聯合所有

從tab2中選擇abs(z*2)+1,其中abs(z*2)+1!=5

按1排序

17.如果子查詢是復合查詢,父查詢的所有ORDER BY語句都必須是對子查詢列的簡單引用。

18.子查詢沒有使用LIMIT,或者外部查詢沒有WHERE語句。

子查詢的展平是通過壹個特殊的函數實現的,它是:

靜態int flattenSubquery(

Parse *pParse,/*解析上下文*/

Select *p,/*父或外部Select語句*/

int iFrom,/* Index in p-& gt;pSrc->內部子查詢的a[]*/

int isAgg,/*如果外部選擇使用聚合函數,則為True */

int subqueryIsAgg /*如果子查詢使用聚合函數,則為True */

)

它在Select.c文件中實現。顯然,對於壹個復雜的查詢,如果在滿足上述條件的情況下,查詢語句被展平,查詢就可以得到優化。如果有指數就更好了!

動詞 (verb的縮寫)連接查詢

在返回查詢結果之前,相關表的每壹行都必須已經連接。在SQLite中,這是通過嵌套循環實現的。在早期版本中,最左邊是最外面的循環,最右邊是最裏面的循環。當連接兩個或多個表時,如果有索引,就放在內循環中,也就是FROM的末尾,因為對於前面選中的每壹行,都會快速找到後面對應的行,如果有索引,否則就是。

優化方法如下:

對於要查詢的每個表,統計該表上的索引信息。首先,將成本分配給SQLITE_BIG_DBL(系統定義的常數):

1)如果沒有索引,查找該表上是否有rowid的查詢條件:

1.如果有Rowid=EXPR,如果有,則返回該表的成本估算,成本為零,查詢得到的記錄數為1,完成該表的成本估算。

2.如果沒有Rowid=EXPR,但在(...)而IN是壹個列表,那麽記錄返回的記錄數就是IN列表中的元素數,估計開銷為NlogN。

3.如果IN不是列表而是子查詢結果,那麽因為無法確定具體的子查詢,所以只能估計壹個值,返回的記錄數是100,代價是200。

4.如果rowid是範圍查詢,那麽估計所有符合條件的記錄是總記錄的三分之壹,總記錄估計為1000000,估計開銷也是記錄數。

5.如果查詢還需要排序,則添加排序的成本NlogN。

6.如果此時得到的成本小於總成本,則更新總成本,否則不更新。

2)如果WHERE子句中有or運算符,則應該單獨分析由這些OR連接的所有子句。

1.如果存在由AND連接符組成的子句,那麽分別分析由AND連接的子句。

2.如果鏈接子句是X的形式

3.下壹步是計算整個OR操作的總成本。

4.如果查詢需要排序,將上述總開銷乘以排序開銷NlogN。

5.如果此時得到的成本小於總成本,則更新總成本,否則不更新。

3)如果有索引,則統計每個表的索引信息。對於每個指數:

1.首先找到這個索引對應的列號,然後找到對應的可以在這個索引中使用的WHERE子句(運算符必須是=或IN(…))。如果沒有找到,那麽退出每個索引的循環。如果找到,判斷這個子句的操作符是什麽。如果是=,那麽就沒有額外的成本。如果是在(子選擇),那就估計壹下。

2.然後計算總費用和總查詢結果記錄和費用。

3.nRow = ppro be-& gt;aiRowEst[I]* in multiplier;/*計算行數*/

4.cost = nRow * est log(in multiplier);/*統計成本*/

5.如果在(…)中找不到operator = or的子句,而是壹個範圍查詢,那麽妳就要把查詢結果中的記錄數估計為nRow/3,估計的成本為cost/3。

6.類似地,如果查詢需要排序,將NlogN添加到上面的總開銷中。

7.如果此時得到的成本小於總成本,則更新總成本,否則不更新。

4)通過上面的優化過程,可以得到壹個表查詢的總開銷(即上述開銷之和),然後對第二個表做同樣的操作,使FROM子句中的所有表都計算出各自的開銷,最後取最小的壹個,這將是嵌套循環的最內層,依次可以得到整個嵌套循環的嵌套順序,此時最優,達到優化的目的。

5)所以循環的嵌套順序不壹定與FROM子句中的順序相同,因為在執行過程中會使用索引優化來重新排列順序。

不及物動詞索引

在SQLite中,有以下索引:

1)單列索引

2)多列索引

3)獨特性指數

4)對於聲明為:INTEGER PRIMARY KEY的主鍵,默認情況下會對該列進行排序,所以雖然在數據字典中沒有對其進行索引,但其作用類似於索引。所以,如果在這個主鍵上單獨建立索引,會浪費空間,沒有任何好處。

使用該指數的註意事項:

1)沒有必要為非常小的表建立索引。

2)如果經常對表進行插入和更新操作,應該控制索引的使用。

3)不要在壹個表上建立太多的索引。如果構建了太多的索引,SQLite可能不會選擇最好的壹個來執行查詢。壹個解決方案是建立壹個聚簇索引。

指數應用的時間:

1)運算符:=、>、& lt,在等

2)運算符BETWEEN、LIKE或不能使用索引。

如between:select * from my table where my field介於10和20之間;

那麽它應該被轉換成:

SELECT * FROM my table WHERE my field & gt;= 10和myfield & lt= 20;

這時候如果myfield上有索引就可以使用,大大提高了速度。

另壹個例子是這樣的:select * from my table其中我的字段就像' SQL % ';

此時,它應該轉換成:

SELECT * FROM my table WHERE my field & gt;= 'sql '和myfield & ltsqm ';

這時候如果myfield上有索引就可以使用,大大提高了速度。

或者:select * from my table where my field = ' ABC '或my field = ' XYZ ';

此時,它應該轉換成:

SELECT * FROM my table WHERE my field IN(' ABC ',' XYZ ');

這時候如果myfield上有索引就可以使用,大大提高了速度。

3)有時候索引用不上,要遍歷整個表(程序演示)。

SELECT * FROM mytable,其中my field % 2 = 1;

SELECT * FROM my table WHERE substr(my field,0,1)= ' w ';

SELECT * FROM my table WHERE length(my field)& lt;5;