在網站準備采用Lucence.net來進行索引處理搜尋慢問題的時候,突然發現常用的分頁擷取資料的row_number也支援不住了,後期查到200多萬的時候非常慢(總資料有500萬),經過網上查詢分析一些資料後,基本上搞明白是什麼原因導緻的,順便紀錄一下解決方案。
在sosobt.com網站準備采用Lucence.net來進行索引處理搜尋慢問題的時候,突然發現常用的分頁擷取資料的row_number也支援不住了,後期查到200多萬的時候非常慢(總資料有500萬),經過網上查詢分析一些資料後,基本上搞明白是什麼原因導緻的,順便紀錄一下解決方案。
------------------------------------
網上找的幾種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)
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,686ms
-----------------------------------------------
個人也是經常采用row_number來解決問題的,但是主鍵是以ID為主的,這次資料庫表不是ID主鍵,
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZwpmLyQmMjR2Y1EmYlVDN0YjZidTZxQjMhR2YlZ2MxkzNhBTL5EzMzYTM0EzLcBTMzEDMy8CXzADO3QzLcd2bsJ2Lc12bj5ycn9Gbi52YuAzcldWYtl2Lc9CX6MHc0RHaiojIsJye.jpg)
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 去看看,休息下...
希望大家多多推薦哦...大家的推薦才是下一篇介紹的動力...