Sqlite的索引優化

2021-06-08 23:48:24 字數 4340 閱讀 2406

一直比較喜歡文字型資料庫,簡單、方便,容易儲存。最近將乙個**的mysql 資料庫轉換成了 2.5g 的 sqlite資料庫。悲劇發生了,非常慢,**經常超出30秒的執行時間,所以一直用快取扛著,10.1 假期正好有空,決定徹底解決下這個慢的問題。

首先是首頁慢,認真的分析了首頁呼叫的函式,發現卡死經常在乙個 collect 表上,開啟collect 表,12萬條資料,保守估計,應該至少佔了1.5 g以上的空間,因為內容資料基本都在這個表上。怪不得慢,就算是物理機的高速硬碟,估計也扛不住這樣的資料吧。

檢視collect 表的索引,發現只有 vtype 和 class 2個整數型索引,將函式的sql語句拿出:

select id,title from collect where vtype=6 and class=0 limit 20

執行竟然要 40多秒!!!悲劇~~~~

馬上建立class和vtype 2個字段的復合索引,建立索引用了將近1分鐘。

然後查詢,速度馬上從40秒下降到 100ms 以內,第2次查詢,速度在20ms以內,第3次,第4次和第2次是乙個數量級的。

ps: 為什麼第1次慢?按理說sqlite這種文字型資料庫應該是沒有快取的,和mysql 、sqlserver這種服務型資料庫來對比,沒有快取應該不會快的啊?  個人認為應該是作業系統的io快取所引起。以前作業系統複製檔案的時候,複製之後刪除,第2次複製,速度塊了很多,很有可能是這個原因。

經過上面的優化,首頁可以在300多ms開啟了,將頁面快取設定為86400秒(也就是一天更新一次),第一次300多ms響應,以後基本上是10ms以內輸出快取,優化成功!

第2個需要優化的頁面為列表頁,12萬條資料分頁顯示,**很簡單:

select id ,title from collect where vtype>=5 and class=0 limit 20

sql語句很快,可是頁面很慢。。一直找不到原因。

後來發現是分頁類的原因,分頁類要求出count總數,有一條:

select count(*) from collect where vtype>=5 and class=0 

my god , 悲劇發生了,2分鐘,整整卡了2分鐘才刷出乙個38049 這個整數。。。為什麼?明明做了復合索引了,怎麼還這麼慢?

於是又嘗試了:select count(*) from collect , select count(*) from collect where vtype>5 , select count(*) from collect where class=0

首先懷疑是不是 >= 出了問題? 於是將 語句改為:

select count(*) from collect where class=0 and vtype>4    (還是很慢)

select count(*) from collect where class=0 and vtype=5      (很快,20ms查詢完)

select count(*) from collect where class=0 and vtype in (5,6)    (很慢)

select count(*) from collect where class=0 and (vtype=5 or vtype=6)    (很慢)

select count(*) from collect where (class=0 and vtype=5) or (class=0 and vtype=6)    (很快,20ms查詢完)

select count(*) from collect where (vtype=5 and class=0) or (class=0 and vtype=6)    (很快)

結論:從上面可以看出,不能對vtype 不能有超過2種可能與 class做 and 操作,就會快,class和 vtyp 的順序對查詢結果沒有影響;至於上面的是走了哪個索引,還沒實驗。

由於sqlite的explain語句沒有mysql好用,無法知道具體的走索引細節,所以只能在此大膽推測+測試得出一些結論。

首先有1個問題: select id from collect where class=0 and vtype>4 limit 20 很快可以查到,證明走了復合索引。但select count(*) from collect where class=0 and vtype> 4   卻很慢。 你說他沒走索引嘛,至少where 後面的絕對走了索引。但你說他走了索引嘛,count(*) 確實在遍歷,也就是索引裡沒記錄總數。

為了驗證為什麼count那麼慢,而limit很快,我做了乙個實驗

select id from collect where class=0 and vtype>4 limit 20       (8ms)

select id from collect where class=0 and vtype>4 limit 200     (16ms)

select id from collect where class=0 and vtype>4 limit 2000     (268ms)

select id from collect where class=0 and vtype>4  (不敢做下去,肯定很卡,基本上會超時)

20條很快,數量越多,越慢,但確實走了索引,沒走索引之前,同樣的語句慢得嚇人,基本上是幾分鐘都出不來。

看下面的語句:

select id from collect where class=0 and vtype=5 limit 20   (0ms)

select id from collect where class=0 and vtype=5 limit 200  (2ms)

select id from collect where class=0 and vtype=5 limit 2000 (8ms)

select id from collect where class=0 and vtype=5                  (243ms,3.8萬條記錄)

上面可以看出,非常快,基本上是上面的10倍以上。和輸出記錄數基本上沒很大差別。

以上2種語句的對比發現:對於復合索引,

1)  >, = 確實都會走索引,做簡單的limit查詢速度都很快;

2)   對於大資料輸出,> 非常耗時,尤其是對於count ,在資料量較大時, 比較符號(<,> ) 將會直接卡死。

3)= 號速度最快,不管是count還是大資料輸出,速度都可以接受,在平時的程式設計中,盡量多用 = 運算子來處理復合索引。

而對於單索引,則沒有影響,不管》, = 速度都非常快。count函式也沒有影響。

1).sqlite3.def: 用於編譯生成相應的lib檔案

2).sqlite3.dll:提供sqlite所需的動態鏈結庫檔案。

3).sqlit3e.exe:執行檔案,用於執行資料庫操作

2. 示例:

1)。開啟乙個cmd程式,進入sqlite目錄,執行:

d:\sqlite>sqlite3.exe my.db   -->建立乙個資料庫檔案my.db

sqlite3>.help    -->

sqlite3>.width [column1_max_width] [column2_max_width] .....

sqlite3>.output [filename] --->output the result to the special file

sqlite3>..tables,可以看資料庫中的所有表; 

sqlite3>.indices,可以列出乙個指定表的所有索引; 

sqlite3>.schema,建立表和索引時候的create語句,也可以在後面指明表名; 

sqlite3>.databases,檢視當前開啟的所有資料庫,通常是乙個main乙個tem

sqlite3>.dump;  匯出的sql語句,可以放到oracle中去執行;

sqlite3>.explain:  就是查詢一條sql語句最終解析出來的執行計畫,對sql語句調優很有用;

sqlite3>.timeout: 預設超時時間是0,查詢一張表或索引,發現表或索引被鎖定,就立刻返回,不等待;

3.侷限性:

1)sqlite只適合對單一檔案進行讀併發操作,不適合對其進行併發寫事務。事務的侷限性,使其應用受限,通常用於處理小型的事務。

2)不支援外來鍵約束; 

3)對觸發器的支援不是很完整; 

4)對alter table的支援不是很完整; 

5)不支援嵌入式事務; 

6)不支援right和full outer join. 

7)不支援檢視的寫更新操作; 

8)不支援grant和revoke;

9)不支援儲存過程

10)檔案鎖:sqlite對事務的併發控制是通過本地檔案鎖低階原語來進行的。若有部分資料殘存於網路分割槽中,檔案鎖將失效。

文章**:

sqlite 復合唯一索引 SQLite索引

索引 index 是一種特殊的查詢表,資料庫搜尋引擎用來加快資料檢索。簡單地說,索引是乙個指向表中資料的指標。乙個資料庫中的索引與一本書後邊的索引是非常相似的。例如,如果您想在一本討論某個話題的書中引用所有頁面,您首先需要指向索引,索引按字母順序列出了所有主題,然後指向乙個或多個特定的頁碼。索引有助...

sqlite 復合唯一索引 SQLite 索引

索引是一種特殊的查詢表,可以使用搜尋引擎的資料庫,以加快資料檢索。簡單地說,索引是乙個指標,表中的資料。乙個資料庫中的索引是非常相似在一本書的背部的索引。例如,如果你想在一本書中引用的所有頁面討論某個話題,先參考索引,按字母順序列出所有主題,再交由乙個或多個特定的頁碼。索引有助於加快select查詢...

sqlite 復合唯一索引 SQLite 索引

sqlite 索引 index 索引 index 是一種特殊的查詢表,資料庫搜尋引擎用來加快資料檢索。簡單地說,索引是乙個指向表中資料的指標。乙個資料庫中的索引與一本書的索引目錄是非常相似的。拿漢語字典的目錄頁 索引 打比方,我們可以按拼音 筆畫 偏旁部首等排序的目錄 索引 快速查詢到需要的字。索引...