移動(dòng)端100萬(wàn)數(shù)據(jù)sqlite語(yǔ)句的搜索查詢優(yōu)化(索引篇)

數(shù)據(jù)庫(kù)的優(yōu)化,最大的一點(diǎn):索引的建立,那么你寫過(guò)這么多的sql語(yǔ)句,真的會(huì)用索引么,或者說(shuō)會(huì)用索引么?體驗(yàn)過(guò)百萬(wàn)級(jí)別的查詢速度么?

為什么要使用索引妖啥?
索引能夠加速表中數(shù)據(jù)的查找和排序晚岭,索引是一個(gè)單獨(dú)建立  的物理數(shù)據(jù)庫(kù),并且包含
一個(gè)指向數(shù)據(jù)表中指定列的數(shù)據(jù)值指針(指向?qū)?yīng)數(shù)據(jù)的指針)囊榜。
作用:
1. 快速查詢數(shù)據(jù)
2.保證數(shù)據(jù)的唯一性
3. 實(shí)現(xiàn)表與表之間的參照完整性
4.在使用order by、group by子句進(jìn)行數(shù)據(jù)檢索時(shí)肛循,利用索引  可以減少排序和分組的時(shí)間甥桂。
優(yōu)點(diǎn):
1. 大大加快數(shù)據(jù)檢索速度
2. 創(chuàng)建唯一索引,保證數(shù)據(jù)庫(kù)表中每行數(shù)據(jù)的唯一性
3. 加速表之間的連接
4. 減少查詢中分組和排序的時(shí)間
缺點(diǎn):
1.需要占用物理空間
2. 對(duì)表中數(shù)據(jù)進(jìn)行增加券时、刪除和修改時(shí)索引也要更新孤里,降低了數(shù)據(jù)維護(hù)速度

一.索引的分類(聚集索引,非聚合索引,復(fù)合索引)

1.聚集(clustered)索引,也叫聚簇索引橘洞。

定義:表中行的物理順序與鍵值的邏輯(索引)順序相同捌袜。因?yàn)閿?shù)據(jù)的物理順序只能有一種,所以一張表只能有一個(gè)聚集索引震檩。如果一張表沒(méi)有聚集索引琢蛤,那么這張表就沒(méi)有順序的概念,所有的新行都會(huì)插入到表的末尾。對(duì)于聚集索引抛虏,葉節(jié)點(diǎn)即存儲(chǔ)了數(shù)據(jù)行博其,不再有單獨(dú)的數(shù)據(jù)頁(yè)。

定義比較抽象,舉個(gè)實(shí)際的例子:
一個(gè)表就像是我們以前用的新華字典迂猴,聚集索引就像是拼音目錄慕淡,而每個(gè)字存放的頁(yè)碼就是我們的數(shù)據(jù)物理地址,我們?nèi)绻樵円粋€(gè)“哇”字沸毁,我們只需要查詢“哇”字對(duì)應(yīng)在新華字典拼音目錄對(duì)應(yīng)的頁(yè)碼峰髓,就可以查詢到對(duì)應(yīng)的“哇”字所在的位置傻寂,而拼音目錄對(duì)應(yīng)的A-Z的字順序,和新華字典實(shí)際存儲(chǔ)的字的順序A-Z也是一樣的携兵,如果我們中文新出了一個(gè)字疾掰,拼音開(kāi)頭第一個(gè)是B,那么他插入的時(shí)候也要按照拼音目錄順序插入到A字的后面
下面看個(gè)數(shù)據(jù),解釋下數(shù)據(jù)物理地址:

地址  id  username    age
0x01    1   小張      11
0x02    2   小紅      12
0x03    3   小華      11
..  ..  ..  ..
0xff    256 小英      12
第一列的地址表示該行數(shù)據(jù)在磁盤中的物理地址徐紧,后面三列才 是我們SQL里面用的表里的列,
其中id是主鍵静檬,建立了聚集索引.結(jié)合上面的表格就可以理解這句話了吧:數(shù)據(jù)行的物理順序與列值的順序相同,
如果我們查詢id比較靠后的數(shù)據(jù)并级,那么這行數(shù)據(jù)的地址在磁盤中的物理地址也會(huì)比較后,而且由于物理排列方式與聚集索引的順序相同,所以也就只能建立一個(gè)聚集索引了.

不理解?咱們?cè)儆脠D來(lái)說(shuō)明


滿二叉樹(shù)

樹(shù)節(jié)點(diǎn)1下面有2和2的節(jié)點(diǎn),也可以看作數(shù)據(jù)節(jié)點(diǎn),是不是可以直接獲取到對(duì)應(yīng)的全部列的數(shù)據(jù)?這個(gè)就是聚集索引所有的優(yōu)勢(shì)

2.創(chuàng)建聚集索引(注:Sqlite不支持聚集索引)

2.1.  如果不創(chuàng)建索引拂檩,系統(tǒng)會(huì)自動(dòng)創(chuàng)建一個(gè)隱含列作為表的聚集索引。
create table t1(
    id int primary key,
    name nvarchar(255)
)
2.2.創(chuàng)建表后添加聚集索引
SQL Server
    create clustered index clustered_index on    table_name(colum_name)
MySQL
    alter table table_name add primary key(colum_name)

  值得注意的是嘲碧,最好還是在創(chuàng)建表的時(shí)候添加聚集索引稻励,由于聚集索引的物理順序上的特殊性,    
  因此如果再在上面創(chuàng)建索引的時(shí)候會(huì)根據(jù)索引列的排序移動(dòng)全部數(shù)據(jù)行上面的順序愈涩,會(huì)非常地耗費(fèi)時(shí)間以及性能望抽。

二.非聚集索引

    定義:該索引中索引的邏輯順序與磁盤上行的物理存儲(chǔ)順序不同,一個(gè)表中可以擁有多個(gè)非
聚集索引钠署。

可以這樣理解:除了聚集索引以外的索引都是非聚集索引糠聪,只是人們想細(xì)分一下非聚集索引,
分成普通索引谐鼎,唯一索引舰蟆,全文索引。如果非要把非聚集索引類比成現(xiàn)實(shí)生活中的東西狸棍,那
么非聚集索引就像新華字典的偏旁字典身害,他結(jié)構(gòu)順序與實(shí)際存放順序不一定一致。

通俗點(diǎn)的理解就是:索引節(jié)點(diǎn)跟聚集節(jié)點(diǎn)是一樣的,只是查詢的時(shí)候,定義的索引在其他列上并沒(méi)有覆蓋,這時(shí)候還得去這個(gè)沒(méi)有覆蓋的列上再查詢,這就需要二次查詢了

    標(biāo)準(zhǔn)的說(shuō)法是:非聚集索引葉節(jié)點(diǎn)仍然是索引節(jié)點(diǎn)草戈,只是有一個(gè)指針指向?qū)?yīng)的數(shù)據(jù)塊塌鸯,此如
果使用非聚集索引查詢,而查詢列中包含了其他該索引沒(méi)有覆蓋的列唐片,那么他還要進(jìn)行第二
次的查詢丙猬,查詢節(jié)點(diǎn)上對(duì)應(yīng)的數(shù)據(jù)行的數(shù)據(jù)。

舉個(gè)例子:   
id    username        age
1        小張          11
2        小紅          12
3        小華          11
..          ..            ..
256      小英          12

以及聚集索引clustered index(id), 非聚集索引index(username)费韭。

使用以下語(yǔ)句進(jìn)行查詢茧球,不需要進(jìn)行二次查詢,直接就可以從非聚集索引的節(jié)點(diǎn)里面就可以獲取
到查詢列的數(shù)據(jù)星持。

select id, username from t1 where username = '小張'
select username from t1 where username = '小張'
但是使用以下語(yǔ)句進(jìn)行查詢抢埋,就需要二次的查詢?nèi)カ@取原數(shù)據(jù)行的score:
select username, age from t1 where username = '小張'

如何解決非聚集索引的二次查詢問(wèn)題?使用復(fù)合索引

三:復(fù)合索引(索引生效講解)

復(fù)合索引(覆蓋索引)顧名思義就是建立兩列以上的索引,即可查詢復(fù)合索引里的列的數(shù)據(jù)而不需要進(jìn)行回表二次查詢,如index(col1, col2)揪垄,執(zhí)行下面的語(yǔ)句:
select col1, col2 from t1 where col1 = 'xxx';

注意:在查詢使用時(shí)穷吮,最好將條件順序按找索引的順序,這樣效率最高

舉些例子:

 CREATE INDEX index_table ON table(x, y, z)創(chuàng)建索引
 那么x,xy,xyz都是前導(dǎo)列饥努,而yz捡鱼,y,z這樣的就不是

索引生效的條件:

  前序列必須使用等于或者in操作最右邊的列可以使用不等式肪凛,這樣索引才可以完全生效堰汉。
同時(shí)辽社,where子句中的列不需要全建立了索引伟墙,但是必須保證建立索引的列之間沒(méi)有間隙
   CREATE INDEX idx_ex1 ON ex1(a,b,c,d,e,...,y,z);

   WHERE a=5 AND b IN (1,2,3) AND c IS NULL AND d='hello'
這顯然對(duì)于abcd四列都是有效的,因?yàn)橹挥械扔诤蚷n操作滴铅,并且是前導(dǎo)列戳葵。

再看三個(gè)查詢語(yǔ)句:
WHERE a=5 AND b IN (1,2,3) AND c>12 AND d='hello'
那這里只有a,b和c的索引會(huì)是有效的汉匙,d列的索引會(huì)失效拱烁,因?yàn)樗赾列的右邊,而c列使用
了不等式噩翠,根據(jù)使用不等式的限制戏自,c列已經(jīng)屬于最右邊。
WHERE b=5 AND c=3 AND d =  'hello'
不生效,沒(méi)有按照索引順序
WHERE  d =  'hello'
不生效,沒(méi)有按照索引順序

最后再看一條:
WHERE b IN (1,2,3) AND c NOT NULL AND d='hello'
索引將不會(huì)被生效伤锚,因?yàn)闆](méi)有使用前導(dǎo)列,a不在擅笔,這個(gè)查詢會(huì)是一個(gè)全表查詢。

對(duì)于between屯援,or猛们,like,都無(wú)法使用索引狞洋。必須要用對(duì)應(yīng)的等式來(lái)生效索引

between:
WHERE scope BETWEEN 100 and 202;
這時(shí)就應(yīng)該將其轉(zhuǎn)換成:
WHERE scope >= 10 AND scope <= 20;

like:
index_table WHERE scope LIKE 'sql%';;
此時(shí)應(yīng)該將它轉(zhuǎn)換成:
WHERE scope >= 'sql' AND scope < 'xxx';

or(用in):
WHERE scope = 'abc' OR scope = 'xyz';
此時(shí)應(yīng)該將它轉(zhuǎn)換成:
WHERE scope IN ('abc', 'xyz');
聚集和非聚集索引區(qū)別

總結(jié):
1.使用聚集索引的查詢效率要比非聚集索引的效率要高弯淘,但是如果需要頻繁去改變聚集索引的值,寫入性能并不高吉懊,因?yàn)樾枰苿?dòng)對(duì)應(yīng)數(shù)據(jù)的物理位置庐橙。
2.非聚集索引在查詢的時(shí)候可以的話就避免二次查詢,這樣性能會(huì)大幅提升借嗽。
3.索引有助于提高檢索性能态鳖,但過(guò)多或不當(dāng)?shù)乃饕矔?huì)導(dǎo)致系統(tǒng)低效。因?yàn)橛脩粼诒碇忻考舆M(jìn)一個(gè)索引淹魄,數(shù)據(jù)庫(kù)就要做更多的工作郁惜。過(guò)多的索引甚至?xí)?dǎo)致索引碎片

聯(lián)想問(wèn)題?:
復(fù)合索引會(huì)替代單一索引么?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子兆蕉,更是在濱河造成了極大的恐慌羽戒,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虎韵,死亡現(xiàn)場(chǎng)離奇詭異易稠,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)包蓝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門驶社,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人测萎,你說(shuō)我怎么就攤上這事亡电。” “怎么了硅瞧?”我有些...
    開(kāi)封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵份乒,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我腕唧,道長(zhǎng)或辖,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任枣接,我火速辦了婚禮颂暇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘但惶。我一直安慰自己耳鸯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布榆骚。 她就那樣靜靜地躺著片拍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪妓肢。 梳的紋絲不亂的頭發(fā)上捌省,一...
    開(kāi)封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音碉钠,去河邊找鬼纲缓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛喊废,可吹牛的內(nèi)容都是我干的祝高。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼污筷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼工闺!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤陆蟆,失蹤者是張志新(化名)和其女友劉穎雷厂,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體叠殷,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡改鲫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了林束。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片像棘。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖壶冒,靈堂內(nèi)的尸體忽然破棺而出缕题,到底是詐尸還是另有隱情,我是刑警寧澤依痊,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布避除,位于F島的核電站,受9級(jí)特大地震影響胸嘁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜凉逛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一性宏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧状飞,春花似錦毫胜、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至焙糟,卻和暖如春口渔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背穿撮。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工缺脉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人悦穿。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓攻礼,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親栗柒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子礁扮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容