在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 去看看,休息下...
但愿你们多多推荐哦...你们的推荐才是下一篇介绍的动力...