在sosobt.com網站準備採用Lucence.net來進行索引處理搜索慢問題的時候,忽然發現經常使用的分頁獲取數據的row_number也支持不住了,後期查到200多萬的時候很是慢(總數據有500萬),通過網上查詢分析一些資料後,基本上搞明白是什麼緣由致使的,順便紀錄一下解決方案。sql
------------------------------------數據庫
網上找的幾種sqlserver2005高效分頁sql查詢語句
top方案:
sql codeselect top 10 * from table1
where id not in(select top 開始的位置 id from table1)服務器
max:
sql codeselect top 10 * from table1
where id>(select max(id)
from (select top 開始位置 id from table1order by id)tt)sqlserver
row:
sql codeselect *
from (
select row_number()over(order by tempcolumn)temprownumber,*
from (select top 開始位置+10 tempcolumn=0,* from table1)t
)tt
where temprownumber>開始位置
3種分頁方式,分別是max方案,top方案,row方案學習
效率:
第1:row
第2:max
第3:top測試
缺點:
max:必須用戶編寫複雜sql,不支持非惟一列排序
top:必須用戶編寫複雜sql,不支持複合主鍵
row:不支持sqlserver2000優化
測試數據:
共320萬條數據,每頁顯示10條數據,分別測試了2萬頁、15萬頁和32萬頁。網站
頁碼,top方案,max方案,row方案
2萬,60ms,46ms,33ms
15萬,453ms,343ms,310ms
32萬,953ms,720ms,686msspa
-----------------------------------------------.net
我的也是常常採用row_number來解決問題的,可是主鍵是以ID爲主的,此次數據庫表不是ID主鍵,
若是使用ID來進行獲取200萬後面的200條數據,發現服務器上須要幾分鐘都不必定出來得結果
select * from (select *,row_number() over(order by ID asc) as RowNum from H31_DHT_TYPE_101_1) as a where RowNum between 2000000 and 2000200
可是使用HashKey來排序,則很快,ms表示毫秒
select * from (select *,row_number() over(order by hashkey asc) as RowNum from H31_DHT_TYPE_101_1) as a where RowNum between 2000000 and 2000200
[2013-10-13 7:32:02]: Addindex[1011]:1500601 DBTime:219ms IndexTime:47ms [2013-10-13 7:32:02]: Addindex[1011]:1500801 DBTime:219ms IndexTime:31ms [2013-10-13 7:32:03]: Addindex[1011]:1501001 DBTime:547ms IndexTime:687ms [2013-10-13 7:32:04]: Addindex[1011]:1501201 DBTime:219ms IndexTime:94ms [2013-10-13 7:32:04]: Addindex[1011]:1501401 DBTime:219ms IndexTime:31ms [2013-10-13 7:32:04]: Addindex[1011]:1501601 DBTime:219ms IndexTime:62ms [2013-10-13 7:32:04]: Addindex[1011]:1501801 DBTime:219ms IndexTime:31ms [2013-10-13 7:32:05]: Addindex[1011]:1502001 DBTime:219ms IndexTime:78ms [2013-10-13 7:32:05]: Addindex[1011]:1502201 DBTime:219ms IndexTime:47ms [2013-10-13 7:32:05]: Addindex[1011]:1502401 DBTime:218ms IndexTime:32ms
因爲hashkey是惟一,但不是遞增的問題,必須以ID遞增來獲取紀錄增長到lucence索引裏面,
在此查詢了什麼時候使用匯集索引或非彙集索引
下面的表總結了什麼時候使用匯集索引或非彙集索引(很重要):
動做描述 | 使用匯集索引 | 使用非彙集索引 |
列常常被分組排序 | 應 | 應 |
返回某範圍內的數據 | 應 | 不該 |
一個或極少不一樣值 | 不該 | 不該 |
小數目的不一樣值 | 應 | 不該 |
大數目的不一樣值 | 不該 | 應 |
頻繁更新的列 | 不該 | 應 |
外鍵列 | 應 | 應 |
主鍵列 | 應 | 應 |
頻繁修改索引列 | 不該 | 應 |
主鍵 | 彙集索引 | |
用途 | 強制表的實體完整性 | 對數據行的排序,方便查詢用 |
一個表多少個 | 一個表最多一個主鍵 | 一個表最多一個彙集索引 |
是否容許多個字段來定義 | 一個主鍵能夠多個字段來定義 | 一個索引能夠多個字段來定義 |
是否容許 null 數據行出現 | 若是要建立的數據列中數據存在null,沒法創建主鍵。 建立表時指定的 PRIMARY KEY 約束列隱式轉換爲 NOT NULL。 |
沒有限制創建彙集索引的列必定必須 not null . 也就是能夠列的數據是 null 參看最後一項比較 |
是否要求數據必須惟一 | 要求數據必須惟一 | 數據便可以惟一,也能夠不惟一。看你定義這個索引的 UNIQUE 設置。 (這一點須要看後面的一個比較,雖然你的數據列可能不惟一,可是系統會替你產生一個你看不到的惟一列) |
建立的邏輯 | 數據庫在建立主鍵同時,會自動創建一個惟一索引。 若是這個表以前沒有彙集索引,同時創建主鍵時候沒有強制指定使用非彙集索引,則創建主鍵時候,同時創建一個惟一的彙集索引 |
若是未使用 UNIQUE 屬性建立彙集索引,數據庫引擎 將向表自動添加一個四字節 uniqueifier 列。 必要時,數據庫引擎 將向行自動添加一個 uniqueifier 值,使每一個鍵惟一。此列和列值供內部使用,用戶不能查看或訪問。 |
經過此處分析聚焦索引一個表只能有一個,如何解決目前的問題呢?
首先咱們分析下
select * from (select *,row_number() over(order by ID asc) as RowNum from H31_DHT_TYPE_101_1) as a where RowNum between 2000000 and 2000200
這條語句的對與錯的問題,
1.select *,row_number() over(order by ID asc) as RowNum from H31_DHT_TYPE_101_1代表了須要查詢全部字段和列所有搜索出來了,數據小的時候你不會發現,但數據量大的時候就知道了,由於他代表了獲取全部字段的數據進行按ID排序,雖然ID也索引了。
2.上面須要很長時間,而後再去定位查詢感受時間很慢。
因此我的的想法是先不用查詢出全部字段的數據,
WITH temp AS (SELECT id, ROW_NUMBER() OVER (ORDER BY id) AS 'RowNumber' FROM H31_DHT_TYPE_101_1)
這條語句查詢出來的結果須要1到2秒,比起上面的基本上須要很長時間算是好的了,
而後再從這裏面取ID號,這樣就節約了很多時間,
WITH temp AS (SELECT id, ROW_NUMBER() OVER (ORDER BY id) AS 'RowNumber' FROM H31_DHT_TYPE_101_1) select ID,hashKey,recvTime,updateTime,keyContent,keyType,recvTimes,fileCnt,filetotalSize,Detail,viewTimes,viewLevel from H31_DHT_TYPE_101_1 where id in (select id from temp where RowNumber between 2000000 and 2000200)
分析使用的時間在2秒左右
[2013-10-14 2:43:17]: Addindex[1011]:2577092 DBTime:1453ms IndexTime:32ms [2013-10-14 2:43:19]: Addindex[1011]:2577292 DBTime:1515ms IndexTime:32ms [2013-10-14 2:43:20]: Addindex[1011]:2577492 DBTime:1578ms IndexTime:31ms [2013-10-14 2:43:22]: Addindex[1011]:2577692 DBTime:1687ms IndexTime:32ms [2013-10-14 2:43:23]: Addindex[1011]:2577892 DBTime:1422ms IndexTime:31ms [2013-10-14 2:43:25]: Addindex[1011]:2578092 DBTime:1547ms IndexTime:31ms [2013-10-14 2:43:27]: Addindex[1011]:2578292 DBTime:1469ms IndexTime:31ms [2013-10-14 2:43:28]: Addindex[1011]:2578492 DBTime:1516ms IndexTime:31ms [2013-10-14 2:43:30]: Addindex[1011]:2578692 DBTime:1422ms IndexTime:31ms [2013-10-14 2:43:36]: Addindex[1011]:2578892 DBTime:6422ms IndexTime:31ms [2013-10-14 2:43:40]: Addindex[1011]:2579092 DBTime:3938ms IndexTime:31ms [2013-10-14 2:43:43]: Addindex[1011]:2579292 DBTime:3484ms IndexTime:32ms [2013-10-14 2:43:48]: Addindex[1011]:2579492 DBTime:4265ms IndexTime:32ms [2013-10-14 2:43:50]: Addindex[1011]:2579692 DBTime:1750ms IndexTime:31ms
總結:
1.對SQL2005的分頁進一步的瞭解了彙集索引的問題,有彙集索引的使用ROW_NUMBER則很快;
2.對目前你們所採用的分頁語句是否合理的問題,優化的問題得了學習,特此記錄一下。
3.但願寫得不對的地方請你們在此留言指教下.
下一篇準備對網站採用lucence.net3.03如何來進行索引搞定搜索的問題進行記錄。
你們看累了,就移步到娛樂區sosobt.com 去看看,休息下...
但願你們多多推薦哦...你們的推薦纔是下一篇介紹的動力...