一直比較喜歡文字型資料庫,簡單、方便,容易儲存。最近將乙個**的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 是一種特殊的查詢表,資料庫搜尋引擎用來加快資料檢索。簡單地說,索引是乙個指向表中資料的指標。乙個資料庫中的索引與一本書的索引目錄是非常相似的。拿漢語字典的目錄頁 索引 打比方,我們可以按拼音 筆畫 偏旁部首等排序的目錄 索引 快速查詢到需要的字。索引...