HOME 首頁
SERVICE 服務(wù)產(chǎn)品
XINMEITI 新媒體代運(yùn)營
CASE 服務(wù)案例
NEWS 熱點(diǎn)資訊
ABOUT 關(guān)于我們
CONTACT 聯(lián)系我們
創(chuàng)意嶺
讓品牌有溫度、有情感
專注品牌策劃15年

    全表查詢速度(什么是全表查詢)

    發(fā)布時(shí)間:2023-04-13 23:18:28     稿源: 創(chuàng)意嶺    閱讀: 59        

    大家好!今天讓創(chuàng)意嶺的小編來大家介紹下關(guān)于全表查詢速度的問題,以下是小編對(duì)此問題的歸納整理,讓我們一起來看看吧。

    開始之前先推薦一個(gè)非常厲害的Ai人工智能工具,一鍵生成原創(chuàng)文章、方案、文案、工作計(jì)劃、工作報(bào)告、論文、代碼、作文、做題和對(duì)話答疑等等

    只需要輸入關(guān)鍵詞,就能返回你想要的內(nèi)容,越精準(zhǔn),寫出的就越詳細(xì),有微信小程序端、在線網(wǎng)頁版、PC客戶端

    官網(wǎng):https://ai.de1919.com。

    創(chuàng)意嶺作為行業(yè)內(nèi)優(yōu)秀的企業(yè),服務(wù)客戶遍布全球各地,如需了解SEO相關(guān)業(yè)務(wù)請(qǐng)撥打電話175-8598-2043,或添加微信:1454722008

    本文目錄:

    全表查詢速度(什么是全表查詢)

    一、這條sql語句 如何能避免全表掃描,增快查詢速度,下面4個(gè)字段都建立了索引

    避免用not in ,not like, <>等等操作

    如果是4個(gè)字段的組合索引那么要注意使用時(shí)候的字段順序

    另外提醒下索引使用不當(dāng)反而會(huì)導(dǎo)致查詢效率低下

    一句兩句講不清楚的,看你自己的經(jīng)驗(yàn)了

    二、Oracle查詢速度優(yōu)化問題

    1. 選用適合的ORACLE優(yōu)化器

    ORACLE的優(yōu)化器共有3種:

    a. RULE (基于規(guī)則) b. COST (基于成本) c. CHOOSE (選擇性)

    設(shè)置缺省的優(yōu)化器,可以通過對(duì)init.ora文件中OPTIMIZER_MODE參數(shù)的各種聲明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS . 你當(dāng)然也在SQL句級(jí)或是會(huì)話(session)級(jí)對(duì)其進(jìn)行覆蓋.

    為了使用基于成本的優(yōu)化器(CBO, Cost-Based Optimizer) , 你必須經(jīng)常運(yùn)行analyze 命令,以增加數(shù)據(jù)庫中的對(duì)象統(tǒng)計(jì)信息(object statistics)的準(zhǔn)確性.

    如果數(shù)據(jù)庫的優(yōu)化器模式設(shè)置為選擇性(CHOOSE),那么實(shí)際的優(yōu)化器模式將和是否運(yùn)行過analyze命令有關(guān). 如果table已經(jīng)被analyze過, 優(yōu)化器模式將自動(dòng)成為CBO , 反之,數(shù)據(jù)庫將采用RULE形式的優(yōu)化器.

    在缺省情況下,ORACLE采用CHOOSE優(yōu)化器, 為了避免那些不必要的全表掃描(full table scan) , 你必須盡量避免使用CHOOSE優(yōu)化器,而直接采用基于規(guī)則或者基于成本的優(yōu)化器.

    2. 訪問Table的方式

    ORACLE 采用兩種訪問表中記錄的方式:

    a. 全表掃描

    全表掃描就是順序地訪問表中每條記錄. ORACLE采用一次讀入多個(gè)數(shù)據(jù)塊(database block)的方式優(yōu)化全表掃描.

    b. 通過ROWID訪問表

    你可以采用基于ROWID的訪問方式情況,提高訪問表的效率, , ROWID包含了表中記錄的物理位置信息..ORACLE采用索引(INDEX)實(shí)現(xiàn)了數(shù)據(jù)和存放數(shù)據(jù)的物理位置(ROWID)之間的聯(lián)系. 通常索引提供了快速訪問ROWID的方法,因此那些基于索引列的查詢就可以得到性能上的提高.

    3. 共享SQL語句

    為了不重復(fù)解析相同的SQL語句,在第一次解析之后, ORACLE將SQL語句存放在內(nèi)存中.這塊位于系統(tǒng)全局區(qū)域SGA(system global area)的共享池(shared buffer pool)中的內(nèi)存可以被所有的數(shù)據(jù)庫用戶共享. 因此,當(dāng)你執(zhí)行一個(gè)SQL語句(有時(shí)被稱為一個(gè)游標(biāo))時(shí),如果它

    和之前的執(zhí)行過的語句完全相同, ORACLE就能很快獲得已經(jīng)被解析的語句以及最好的

    執(zhí)行路徑. ORACLE的這個(gè)功能大大地提高了SQL的執(zhí)行性能并節(jié)省了內(nèi)存的使用.

    可惜的是ORACLE只對(duì)簡單的表提供高速緩沖(cache buffering) ,這個(gè)功能并不適用于多表連接查詢.

    數(shù)據(jù)庫管理員必須在init.ora中為這個(gè)區(qū)域設(shè)置合適的參數(shù),當(dāng)這個(gè)內(nèi)存區(qū)域越大,就可以保留更多的語句,當(dāng)然被共享的可能性也就越大了.

    當(dāng)你向ORACLE 提交一個(gè)SQL語句,ORACLE會(huì)首先在這塊內(nèi)存中查找相同的語句.

    這里需要注明的是,ORACLE對(duì)兩者采取的是一種嚴(yán)格匹配,要達(dá)成共享,SQL語句必須完全相同(包括空格,換行等).

    4.選擇最有效率的表名順序(只在基于規(guī)則的優(yōu)化器中有效)

    ORACLE的解析器按照從右到左的順序處理FROM子句中的表名,因此FROM子句中寫在最后的表(基礎(chǔ)表 driving table)將被最先處理. 在FROM子句中包含多個(gè)表的情況下,你必須選擇記錄條數(shù)最少的表作為基礎(chǔ)表.當(dāng)ORACLE處理多個(gè)表時(shí), 會(huì)運(yùn)用排序及合并的方式連接它們.首先,掃描第一個(gè)表(FROM子句中最后的那個(gè)表)并對(duì)記錄進(jìn)行派序,然后掃描第二個(gè)表(FROM子句中最后第二個(gè)表),最后將所有從第二個(gè)表中檢索出的記錄與第一個(gè)表中合適記錄進(jìn)行合并.如果有3個(gè)以上的表連接查詢, 那就需要選擇交叉表(intersection table)作為基礎(chǔ)表, 交叉表是指那個(gè)被其他表所引用的表.

    5. WHERE子句中的連接順序.

    ORACLE采用自下而上的順序解析WHERE子句,根據(jù)這個(gè)原理,表之間的連接必須寫在其他WHERE條件之前, 那些可以過濾掉最大數(shù)量記錄的條件必須寫在WHERE子句的末尾.

    6. SELECT子句中避免使用 ‘ * ‘

    當(dāng)你想在SELECT子句中列出所有的COLUMN時(shí),使用動(dòng)態(tài)SQL列引用 ‘*' 是一個(gè)方便的方法.不幸的是,這是一個(gè)非常低效的方法. 實(shí)際上,ORACLE在解析的過程中, 會(huì)將'*' 依次轉(zhuǎn)換成所有的列名, 這個(gè)工作是通過查詢數(shù)據(jù)字典完成的, 這意味著將耗費(fèi)更多的時(shí)間.

    7. 減少訪問數(shù)據(jù)庫的次數(shù)

    當(dāng)執(zhí)行每條SQL語句時(shí), ORACLE在內(nèi)部執(zhí)行了許多工作: 解析SQL語句, 估算索引的利用率, 綁定變量 , 讀數(shù)據(jù)塊等等. 由此可見, 減少訪問數(shù)據(jù)庫的次數(shù) , 就能實(shí)際上減少ORACLE的工作量.

    注意: 在SQL*Plus , SQL*Forms和Pro*C中重新設(shè)置ARRAYSIZE參數(shù), 可以增加每次數(shù)據(jù)庫訪問的檢索數(shù)據(jù)量 ,建議值為200.

    8. 使用DECODE函數(shù)來減少處理時(shí)間

    使用DECODE函數(shù)可以避免重復(fù)掃描相同記錄或重復(fù)連接相同的表.

    9. 整合簡單,無關(guān)聯(lián)的數(shù)據(jù)庫訪問

    如果你有幾個(gè)簡單的數(shù)據(jù)庫查詢語句,你可以把它們整合到一個(gè)查詢中(即使它們之間沒有關(guān)系)

    10. 刪除重復(fù)記錄

    最高效的刪除重復(fù)記錄方法 ( 因?yàn)槭褂昧薘OWID)

    DELETE FROM EMP E

    WHERE E.ROWID > (SELECT MIN(X.ROWID)

    FROM EMP X

    WHERE X.EMP_NO = E.EMP_NO);

    11. 用EXISTS替代IN

    在許多基于基礎(chǔ)表的查詢中,為了滿足一個(gè)條件,往往需要對(duì)另一個(gè)表進(jìn)行聯(lián)接.在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率.

    12. 用NOT EXISTS替代NOT IN

    在子查詢中,NOT IN子句將執(zhí)行一個(gè)內(nèi)部的排序和合并. 無論在哪種情況下,NOT IN都是最低效的 (因?yàn)樗鼘?duì)子查詢中的表執(zhí)行了一個(gè)全表遍歷). 為了避免使用NOT IN ,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS

    三、oracle 多表查詢速度太慢。求幫我優(yōu)化一下

    你寫表關(guān)聯(lián)條件的時(shí)候使用了 OR

    那就是說任何一個(gè)條件滿足就會(huì)被檢索出來,所以產(chǎn)生大量笛卡爾集(就是重復(fù)數(shù)據(jù))

    那么5表查詢就會(huì)產(chǎn)生(tb_jbjxx的數(shù)據(jù)件數(shù)* tb_ajjbxx的數(shù)據(jù)件數(shù)*tb_sarjbxx的數(shù)據(jù)件數(shù)*tb_xyr的數(shù)據(jù)件數(shù)*tb_chengbaoxinxi的數(shù)據(jù)件數(shù))件數(shù)據(jù)。

    所以應(yīng)該把表關(guān)聯(lián)的條件修改為 AND

    修改后SQL文如下:

    select jbjxxid,anjianmingcheng,JBJXXSLBH,SARJBXXID,SARMC,JBDWMC

    from tb_jbjxx,tb_ajjbxx,tb_sarjbxx,tb_xyr,tb_chengbaoxinxi

    where tb_jbjxx.JBJXXID=tb_ajjbxx.JBJXXSLBH

    AND tb_ajjbxx.QTRYXXSLBH=tb_sarjbxx.SARJBXXID

    AND tb_sarjbxx.XXLYYWID=tb_xyr.XYRLYYWID

    AND tb_chengbaoxinxi.XXLYYWID=tb_ajjbxx.XXLYYWID

    AND tb_jbjxx. like '東城建國%';

    如果你想要的是滿足任何一個(gè)條件就要檢索出來的話,那么一定要有一個(gè)主表,

    就是查詢主表的所有信息,再用其他表的字段和主表關(guān)聯(lián),有數(shù)據(jù)顯示,沒有數(shù)據(jù)不顯示

    分析你的SQL文,我推測(cè)tb_ajjbxx表是主表的概率比較高,那么SQL文的修改如下:

    select jbjxxid,anjianmingcheng,JBJXXSLBH,SARJBXXID,SARMC,JBDWMC

    from tb_jbjxx,tb_ajjbxx,tb_sarjbxx,tb_xyr,tb_chengbaoxinxi

    where tb_ajjbxx.JBJXXSLBH = tb_jbjxx.JBJXXID(+)

    AND tb_ajjbxx.QTRYXXSLBH = tb_sarjbxx.SARJBXXID(+)

    AND tb_ajjbxx.XXLYYWID = tb_chengbaoxinxi.XXLYYWID(+)

    AND tb_sarjbxx.XXLYYWID = tb_xyr.XYRLYYWID

    AND tb_jbjxx. like '東城建國%';

    --1)where條件的順序修改了,為了提高效率

    --2)where條件中=號(hào)左右內(nèi)容部分交換了,為了增強(qiáng)可讀性

    --3)增加外關(guān)聯(lián)符號(hào)(+)

    最后,關(guān)于多表關(guān)聯(lián),表關(guān)聯(lián)條件必須使用"AND"關(guān)鍵字,否則無效。

    用你做成的SQL文檢索,哪怕5個(gè)表都只有10條數(shù)據(jù)也會(huì)檢索出1萬件結(jié)果,如果各個(gè)表數(shù)據(jù)超過100件,你的檢索結(jié)果集會(huì)是天文數(shù)字。。。如果我的回答沒有直接解決問題,可以追問。

    四、如何優(yōu)化sqlite的查詢速度

    SQLite是個(gè)典型的嵌入式DBMS,它有很多優(yōu)點(diǎn),它是輕量級(jí)的,在編譯之后很小,其中一個(gè)原因就是在查詢優(yōu)化方面比較簡單,它只是運(yùn)用索引機(jī)制來進(jìn)行優(yōu)化的,經(jīng)過對(duì)SQLite的查詢優(yōu)化的分析以及對(duì)源代碼的研究,我將SQLite的查詢優(yōu)總結(jié)如下:

    一、影響查詢性能的因素:

    1. 對(duì)表中行的檢索數(shù)目,越小越好

    2. 排序與否。

    3. 是否要對(duì)一個(gè)索引。

    4. 查詢語句的形式

    二、幾個(gè)查詢優(yōu)化的轉(zhuǎn)換

    1. 對(duì)于單個(gè)表的單個(gè)列而言,如果都有形如T.C=expr這樣的子句,并且都是用OR操作符連接起來,形如: x = expr1 OR expr2 = x OR x = expr3 此時(shí)由于對(duì)于OR,在SQLite中不能利用索引來優(yōu)化,所以可以將它轉(zhuǎn)換成帶有IN操作符的子句:x IN(expr1,expr2,expr3)這樣就可以用索引進(jìn)行優(yōu)化,效果很明顯,但是如果在都沒有索引的情況下OR語句執(zhí)行效率會(huì)稍優(yōu)于IN語句的效率。

    2. 如果一個(gè)子句的操作符是BETWEEN,在SQLite中同樣不能用索引進(jìn)行優(yōu)化,所以也要進(jìn)行相應(yīng)的等價(jià)轉(zhuǎn)換: 如:a BETWEEN b AND c可以轉(zhuǎn)換成:(a BETWEEN b AND c) AND (a>=b) AND (a<=c)。 在上面這個(gè)子句中, (a>=b) AND (a<=c)將被設(shè)為dynamic且是(a BETWEEN b AND c)的子句,那么如果BETWEEN語句已經(jīng)編碼,那么子句就忽略不計(jì),如果存在可利用的index使得子句已經(jīng)滿足條件,那么父句則被忽略。

    3. 如果一個(gè)單元的操作符是LIKE,那么將做下面的轉(zhuǎn)換:x LIKE ‘a(chǎn)bc%’,轉(zhuǎn)換成:x>=‘a(chǎn)bc’ AND x<‘a(chǎn)bd’。因?yàn)樵赟QLite中的LIKE是不能用索引進(jìn)行優(yōu)化的,所以如果存在索引的話,則轉(zhuǎn)換后和不轉(zhuǎn)換相差很遠(yuǎn),因?yàn)閷?duì)LIKE不起作用,但如果不存在索引,那么LIKE在效率方面也還是比不上轉(zhuǎn)換后的效率的。

    三、 幾種查詢語句的處理(復(fù)合查詢)

    1.查詢語句為:<SelectA> <operator> <selectB> ORDER BY <orderbylist> ORDER BY

    執(zhí)行方法: is one of UNION ALL, UNION, EXCEPT, or INTERSECT. 這個(gè)語句的執(zhí)行過程是先將selectA和selectB執(zhí)行并且排序,再對(duì)兩個(gè)結(jié)果掃描處理,對(duì)上面四種操作是不同的,將執(zhí)行過程分成七個(gè)子過程:

    outA: 將selectA的結(jié)果的一行放到最終結(jié)果集中

    outB: 將selectA的結(jié)果的一行放到最終結(jié)果集中(只有UNION操作和UNION ALL操作,其它操作都不放入最終結(jié)果集中)

    AltB: 當(dāng)selectA的當(dāng)前記錄小于selectB的當(dāng)前記錄

    AeqB: 當(dāng)selectA的當(dāng)前記錄等于selectB的當(dāng)前記錄

    AgtB: 當(dāng)selectA的當(dāng)前記錄大于selectB的當(dāng)前記錄

    EofA: 當(dāng)selectA的結(jié)果遍歷完

    EofB: 當(dāng)selectB的結(jié)果遍歷完

    下面就是四種操作的執(zhí)行過程:

     執(zhí)行順序

    UNION ALL

    UNION

    EXCEPT

    INTERSECT

    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

    halt

    halt

    EofB:

    outA, nextA

    outA, nextA

    outA,nextA

    halt

    2. 如果可能的話,可以把一個(gè)用到GROUP BY查詢的語句轉(zhuǎn)換成DISTINCT語句來查詢,因?yàn)镚ROUP BY有時(shí)候可能會(huì)用到index,而對(duì)于DISTINCT都不會(huì)用到索引的 。

    四、子查詢扁平化

    例子:SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5

    對(duì)這個(gè)SQL語句的執(zhí)行一般默認(rèn)的方法就是先執(zhí)行內(nèi)查詢,把結(jié)果放到一個(gè)臨時(shí)表中,再對(duì)這個(gè)表進(jìn)行外部查詢,這就要對(duì)數(shù)據(jù)處理兩次,另外這個(gè)臨時(shí)表沒有索引,所以對(duì)外部查詢就不能進(jìn)行優(yōu)化了,如果對(duì)上面的SQL進(jìn)行處理后可以得到如下SQL語句:SELECT x+y AS a FROM t1 WHERE z<100 AND a>5,這個(gè)結(jié)果顯然和上面的一樣,但此時(shí)只需要對(duì)

    數(shù)據(jù)進(jìn)行查詢一次就夠了,另外如果在表t1上有索引的話就避免了遍歷整個(gè)表。

    運(yùn)用flatten方法優(yōu)化SQL的條件:

    1.子查詢和外查詢沒有都用集函數(shù)

    2.子查詢沒有用集函數(shù)或者外查詢不是個(gè)表的連接

    3.子查詢不是一個(gè)左外連接的右操作數(shù)

    4.子查詢沒有用DISTINCT或者外查詢不是個(gè)表的連接

    5.子查詢沒有用DISTINCT或者外查詢沒有用集函數(shù)

    6.子查詢沒有用集函數(shù)或者外查詢沒有用關(guān)鍵字DISTINCT

    7.子查詢有一個(gè)FROM語句

    8.子查詢沒有用LIMIT或者外查詢不是表的連接

    9.子查詢沒有用LIMIT或者外查詢沒有用集函數(shù)

    10.子查詢沒有用集函數(shù)或者外查詢沒用LIMIT

    11.子查詢和外查詢不是同時(shí)是ORDER BY子句

    12.子查詢和外查詢沒有都用LIMIT

    13.子查詢沒有用OFFSET

    14.外查詢不是一個(gè)復(fù)合查詢的一部分或者子查詢沒有同時(shí)用關(guān)鍵字ORDER BY和LIMIT

    15.外查詢沒有用集函數(shù)子查詢不包含ORDER BY

    16.復(fù)合子查詢的扁平化:子查詢不是一個(gè)復(fù)合查詢,或者他是一個(gè)UNION ALL復(fù)合查詢,但他是都由若干個(gè)非集函數(shù)的查詢構(gòu)成,他的父查詢不是一個(gè)復(fù)合查詢的子查詢,也沒有用集函數(shù)或者是DISTINCT查詢,并且在FROM語句中沒有其它的表或者子查詢,父查詢和子查詢可能會(huì)包含WHERE語句,這些都會(huì)受到上面11、12、13條件的限制。

    例: SELECT a+1 FROM (

    SELECT x FROM tab

    UNION ALL

    SELECT y FROM tab

    UNION ALL

    SELECT abs(z*2) FROM tab2

    ) WHERE a!=5 ORDER BY 1

    轉(zhuǎn)換為:

    SELECT x+1 FROM tab WHERE x+1!=5

    UNION ALL

    SELECT y+1 FROM tab WHERE y+1!=5

    UNION ALL

    SELECT abs(z*2)+1 FROM tab2 WHERE abs(z*2)+1!=5

    ORDER BY 1

    17.如果子查詢是一個(gè)復(fù)合查詢,那么父查詢的所有的ORDER BY語句必須是對(duì)子查詢的列的簡單引用

    18.子查詢沒有用LIMIT或者外查詢不具有WHERE語句

    子查詢扁平化是由專門一個(gè)函數(shù)實(shí)現(xiàn)的,函數(shù)為:

    static int flattenSubquery(

    Parse *pParse, /* Parsing context */

    Select *p, /* The parent or outer SELECT statement */

    int iFrom, /* Index in p->pSrc->a[] of the inner subquery */

    int isAgg, /* True if outer SELECT uses aggregate functions */

    int subqueryIsAgg /* True if the subquery uses aggregate functions */

    )

    它是在Select.c文件中實(shí)現(xiàn)的。顯然對(duì)于一個(gè)比較復(fù)雜的查詢,如果滿足上面的條件時(shí)對(duì)這個(gè)查詢語句進(jìn)行扁平化處理后就可以實(shí)現(xiàn)對(duì)查詢的優(yōu)化。如果正好存在索引的話效果會(huì)更好!

    五、連接查詢

    在返回查詢結(jié)果之前,相關(guān)表的每行必須都已經(jīng)連接起來,在SQLite中,這是用嵌套循環(huán)實(shí)現(xiàn)的,在早期版本中,最左邊的是最外層循環(huán),最右邊的是最內(nèi)層循環(huán),連接兩個(gè)或者更多的表時(shí),如果有索引則放到內(nèi)層循環(huán)中,也就是放到FROM最后面,因?yàn)閷?duì)于前面選中的每行,找后面與之對(duì)應(yīng)的行時(shí),如果有索引則會(huì)很快,如果沒有則要遍歷整個(gè)表,這樣效率就很低,但在新版本中,這個(gè)優(yōu)化已經(jīng)實(shí)現(xiàn)。

    優(yōu)化的方法如下:

    對(duì)要查詢的每個(gè)表,統(tǒng)計(jì)這個(gè)表上的索引信息,首先將代價(jià)賦值為SQLITE_BIG_DBL(一個(gè)系統(tǒng)已經(jīng)定義的常量):

    1) 如果沒有索引,則找有沒有在這個(gè)表上對(duì)rowid的查詢條件:

    1.如果有Rowid=EXPR,如果有的話則返回對(duì)這個(gè)表代價(jià)估計(jì),代價(jià)計(jì)為零,查詢得到的記錄數(shù)為1,并完成對(duì)這個(gè)表的代價(jià)估計(jì),

    2.如果沒有Rowid=EXPR 但有rowid IN (...),而IN是一個(gè)列表,那么記錄返回記錄數(shù)為IN列表中元素的個(gè)數(shù),估計(jì)代價(jià)為NlogN,

    3.如果IN不是一個(gè)列表而是一個(gè)子查詢結(jié)果,那么由于具體這個(gè)子查詢不能確定,所以只能估計(jì)一個(gè)值,返回記錄數(shù)為100,代價(jià)為200。

    4.如果對(duì)rowid是范圍的查詢,那么就估計(jì)所有符合條件的記錄是總記錄的三分之一,總記錄估計(jì)為1000000,并且估計(jì)代價(jià)也為記錄數(shù)。

    5.如果這個(gè)查詢還要求排序,則再另外加上排序的代價(jià)NlogN

    6.如果此時(shí)得到的代價(jià)小于總代價(jià),那么就更新總代價(jià),否則不更新。

    2) 如果WHERE子句中存在OR操作符,那么要把這些OR連接的所有子句分開再進(jìn)行分析。

    1. 如果有子句是由AND連接符構(gòu)成,那么再把由AND連接的子句再分別分析。

    2. 如果連接的子句的形式是X<op><expr>,那么就再分析這個(gè)子句。

    3. 接下來就是把整個(gè)對(duì)OR操作的總代價(jià)計(jì)算出來。

    4. 如果這個(gè)查詢要求排序,則再在上面總代價(jià)上再乘上排序代價(jià)NlogN

    5. 如果此時(shí)得到的代價(jià)小于總代價(jià),那么就更新總代價(jià),否則不更新。

    3) 如果有索引,則統(tǒng)計(jì)每個(gè)表的索引信息,對(duì)于每個(gè)索引:

    1. 先找到這個(gè)索引對(duì)應(yīng)的列號(hào),再找到對(duì)應(yīng)的能用到(操作符必須為=或者是IN(…))這個(gè)索引的WHERE子句,如果沒有找到,則退出對(duì)每個(gè)索引的循環(huán),如果找到,則判斷這個(gè)子句的操作符是什么,如果是=,那么沒有附加的代價(jià),如果是IN(sub-select),那么估計(jì)它附加代價(jià)inMultiplier為25,如果是IN(list),那么附加代價(jià)就是N(N為list的列數(shù))。

    2. 再計(jì)算總的代價(jià)和總的查詢結(jié)果記錄數(shù)和代價(jià)。

    3. nRow = pProbe->aiRowEst[i] * inMultiplier;/*計(jì)算行數(shù)*/

    4. cost = nRow * estLog(inMultiplier);/*統(tǒng)計(jì)代價(jià)*/

    5. 如果找不到操作符為=或者是IN(…)的子句,而是范圍的查詢,那么同樣只好估計(jì)查詢結(jié)果記錄數(shù)為nRow/3,估計(jì)代價(jià)為cost/3。

    6. 同樣,如果此查詢要求排序的話,再在上面的總代價(jià)上加上NlogN

    7. 如果此時(shí)得到的代價(jià)小于總代價(jià),那么就更新總代價(jià),否則不更新。

    4) 通過上面的優(yōu)化過程,可以得到對(duì)一個(gè)表查詢的總代價(jià)(就是上面各個(gè)代價(jià)的總和),再對(duì)第二個(gè)表進(jìn)行同樣的操作,這樣如此直到把FROM子句中所有的表都計(jì)算出各自的代價(jià),最后取最小的,這將作為嵌套循環(huán)的最內(nèi)層,依次可以得到整個(gè)嵌套循環(huán)的嵌套順序,此時(shí)正是最優(yōu)的,達(dá)到了優(yōu)化的目的。

    5) 所以循環(huán)的嵌套順序不一定是與FROM子句中的順序一致,因?yàn)樵趫?zhí)行過程中會(huì)用索引優(yōu)化來重新排列順序。

    六、索引

    在SQLite中,有以下幾種索引:

    1) 單列索引

    2) 多列索引

    3) 唯一性索引

    4) 對(duì)于聲明為:INTEGER PRIMARY KEY的主鍵來說,這列會(huì)按默認(rèn)方式排序,所以雖然在數(shù)據(jù)字典中沒有對(duì)它生成索引,但它的功能就像個(gè)索引。所以如果在這個(gè)主鍵上在單獨(dú)建立索引的話,這樣既浪費(fèi)空間也沒有任何好處。

    運(yùn)用索引的注意事項(xiàng):

    1) 對(duì)于一個(gè)很小的表來說沒必要建立索引

    2) 在一個(gè)表上如果經(jīng)常做的是插入更新操作,那么就要節(jié)制使用索引

    3) 也不要在一個(gè)表上建立太多的索引,如果建立太多的話那么在查詢的時(shí)候SQLite可能不會(huì)選擇最好的來執(zhí)行查詢,一個(gè)解決辦法就是建立聚蔟索引

    索引的運(yùn)用時(shí)機(jī):

    1) 操作符:=、>、<、IN等

    2) 操作符BETWEEN、LIKE、OR不能用索引,

    如BETWEEN:SELECT * FROM mytable WHERE myfield BETWEEN 10 and 20;

    這時(shí)就應(yīng)該將其轉(zhuǎn)換成:

    SELECT * FROM mytable WHERE myfield >= 10 AND myfield <= 20;

    此時(shí)如果在myfield上有索引的話就可以用了,大大提高速度

    再如LIKE:SELECT * FROM mytable WHERE myfield LIKE 'sql%';

    此時(shí)應(yīng)該將它轉(zhuǎn)換成:

    SELECT * FROM mytable WHERE myfield >= 'sql' AND myfield < 'sqm';

    此時(shí)如果在myfield上有索引的話就可以用了,大大提高速度

    再如OR:SELECT * FROM mytable WHERE myfield = 'abc' OR myfield = 'xyz';

    此時(shí)應(yīng)該將它轉(zhuǎn)換成:

    SELECT * FROM mytable WHERE myfield IN ('abc', 'xyz');

    此時(shí)如果在myfield上有索引的話就可以用了,大大提高速度

    3) 有些時(shí)候索引都是不能用的,這時(shí)就應(yīng)該遍歷全表(程序演示)

    SELECT * FROM mytable WHERE myfield % 2 = 1;

    SELECT * FROM mytable WHERE substr(myfield, 0, 1) = 'w';

    SELECT * FROM mytable WHERE length(myfield) < 5;

    以上就是關(guān)于全表查詢速度相關(guān)問題的回答。希望能幫到你,如有更多相關(guān)問題,您也可以聯(lián)系我們的客服進(jìn)行咨詢,客服也會(huì)為您講解更多精彩的知識(shí)和內(nèi)容。


    推薦閱讀:

    公司稱呼大全表(公司稱呼大全表格圖片)

    全表查詢速度(什么是全表查詢)

    英文音標(biāo)發(fā)音大全表

    花境搭配景觀設(shè)計(jì)(花境搭配景觀設(shè)計(jì)方案)

    睢縣美食排行榜(睢縣美食排行榜最新)