目前的视图 表索引没有起作用,尤其用到了范围查询。调整如下: 第一步:tb_Product 表是主表 把主键聚集索引取消,保存表结构更改。 第二步:tb_Product 表 上的releasetimeandpagerrank0索引 设置成聚集索引,保存表结构更改。 第三步:现在关不缓存测试 现有查询11秒。 第四步:不用视图直接写查询: --清空数据缓存和执行计划缓存 DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE --查看IO和Time set statistics io on set statistics time onSELECT b.rownum, a.* FROM tb_Product a, (SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum, pagerrank0,releaseTime,productid FROM tb_Product WHERE isPassAudit='true' and pagerRank0>0 ) AS b WHERE b.pagerrank0 =a.pagerrank0 and b.releaseTime =a.releaseTime and b.productid=a.productid AND b.rownum BETWEEN 159985 AND 160000 ORDER BY b.rownum 执行时间不到1秒 第五步:主表查询出来后再去连接附表,这步省略。
这样加索引试试: create index ix_02 on view_product(isPassAudit,pagerRank0,releaseTime)加了上面的索引,试试这面的sql速度:SELECT * FROM ( SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum, isPassAudit FROM view_product WHERE isPassAudit='true' and pagerRank0>0 ) AS D WHERE rownum BETWEEN 159985 AND 160000 ORDER BY pagerrank0 DESC , releaseTime desc
SELECT b.rownum, a.* FROM tb_Product a, (SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum, * FROM tb_Product WHERE isPassAudit='true' and pagerRank0>0 ) AS b WHERE b.pagerrank0 =a.pagerrank0 and b.releaseTime =a.releaseTime and b.productid=a.productid AND b.rownum BETWEEN 159985 AND 160000 ORDER BY b.rownum 改成*,这样速度如何,io如何?
to hyqok: SELECT b.rownum, a.* FROM tb_Product a, (SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum, * FROM tb_Product WHERE isPassAudit='true' and pagerRank0>0 ) AS b WHERE b.pagerrank0 =a.pagerrank0 and b.releaseTime =a.releaseTime and b.productid=a.productid AND b.rownum BETWEEN 10 AND 20 ORDER BY b.rownum这个读page如何?
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间: CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。(11 行受影响) 表 'tb_Product'。扫描计数 12,逻辑读取 45 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。SQL Server 执行时间: CPU 时间 = 16 毫秒,占用时间 = 2 毫秒。
-- BETWEEN 159985 AND 160000SQL Server 分析和编译时间: CPU 时间 = 0 毫秒,占用时间 = 34 毫秒。 DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。SQL Server 执行时间: CPU 时间 = 31 毫秒,占用时间 = 27 毫秒。 DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。SQL Server 执行时间: CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间: CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间: CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。(16 行受影响) 表 'tb_Product'。扫描计数 17,逻辑读取 20345 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。SQL Server 执行时间: CPU 时间 = 156 毫秒,占用时间 = 180 毫秒。
利用您的代码。 DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE --查看IO和Time set statistics io on set statistics time on SELECT b.rownum, a.* FROM tb_Product a, (SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum, pagerrank0,releaseTime,productid FROM tb_Product WHERE isPassAudit='true' and pagerRank0>0 ) AS b WHERE b.pagerrank0 =a.pagerrank0 and b.releaseTime =a.releaseTime and b.productid=a.productid AND b.rownum BETWEEN 159985 AND 160000 ORDER BY b.rownum 最后的运行结果如下: SQL Server 分析和编译时间: CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间: CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。 SQL Server 分析和编译时间: CPU 时间 = 31 毫秒,占用时间 = 56 毫秒。 DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。SQL Server 执行时间: CPU 时间 = 16 毫秒,占用时间 = 13 毫秒。 DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。SQL Server 执行时间: CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间: CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间: CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。(16 行受影响) 表 'tb_Product'。扫描计数 17,逻辑读取 21768 次,物理读取 1 次,预读 22464 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。(1 行受影响)SQL Server 执行时间: CPU 时间 = 281 毫秒,占用时间 = 9179 毫秒。 SQL Server 分析和编译时间: CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间: CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。 也就是总共用时:9秒 不知道你的测试环境的配置是什么,我的是双核2.2,3G内存的笔记本上测试的。而你的测试是1秒以内,怎么会有如此大的差异的?
to hyqok:你看这样优化试试呢?我这没数据假设productid 为主键且为聚集索引 再建一个非聚集索引 create index ix_01 on tb_Product(isPassAudit desc,pagerRank0 desc,releaseTime desc)那么先看一下,下面这个查询的io是多少? SELECT * FROM ( SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum, pagerrank0,releaseTime,productid FROM tb_Product WITH(index=ix_01) WHERE isPassAudit='true' and pagerRank0>0 ) AS B WHERE b.rownum BETWEEN 159985 AND 160000待测试结果。
从理论角度上来讲: SELECT * FROM ( SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum, pagerrank0,releaseTime,productid FROM tb_Product WITH(index=ix_01) WHERE isPassAudit='true' and pagerRank0>0 ) AS B WHERE b.rownum BETWEEN 159985 AND 160000 在建索引: create index ix_01 on tb_Product(isPassAudit desc,pagerRank0 desc,releaseTime desc) 后,只读这个非聚集索引的page. 而且这个page是按照查询条件排过序的,理论上row_number()应该是很快的。手头上没有数据,以上只是推断。如果这样设置为了还是几W个page,我无语。
一种是取消这个函数,另行找分页算法。
还有一种是把整个view_product直接保存和驻留到内存中,这样就无需进行大量的IO磁盘读取了。就可以大大加快速度
第一步:tb_Product 表是主表 把主键聚集索引取消,保存表结构更改。
第二步:tb_Product 表 上的releasetimeandpagerrank0索引 设置成聚集索引,保存表结构更改。
第三步:现在关不缓存测试 现有查询11秒。
第四步:不用视图直接写查询:
--清空数据缓存和执行计划缓存
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE --查看IO和Time
set statistics io on
set statistics time onSELECT b.rownum, a.*
FROM tb_Product a,
(SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum,
pagerrank0,releaseTime,productid
FROM tb_Product WHERE isPassAudit='true' and pagerRank0>0 ) AS b
WHERE b.pagerrank0 =a.pagerrank0 and b.releaseTime =a.releaseTime and b.productid=a.productid
AND b.rownum BETWEEN 159985 AND 160000
ORDER BY b.rownum
执行时间不到1秒
第五步:主表查询出来后再去连接附表,这步省略。
这样加索引试试:
create index ix_02 on view_product(isPassAudit,pagerRank0,releaseTime)加了上面的索引,试试这面的sql速度:SELECT * FROM ( SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum, isPassAudit
FROM view_product WHERE isPassAudit='true' and pagerRank0>0 ) AS D
WHERE rownum BETWEEN 159985 AND 160000 ORDER BY pagerrank0 DESC , releaseTime desc
FROM tb_Product a,
(SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum,
*
FROM tb_Product WHERE isPassAudit='true' and pagerRank0>0 ) AS b
WHERE b.pagerrank0 =a.pagerrank0 and b.releaseTime =a.releaseTime and b.productid=a.productid
AND b.rownum BETWEEN 159985 AND 160000
ORDER BY b.rownum 改成*,这样速度如何,io如何?
表 'tb_Product'。扫描计数 1,逻辑读取 20544 次,物理读取 12 次,预读 22032 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(16 行受影响)
表 'View_Product'。扫描计数 1,逻辑读取 490452 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
SELECT b.rownum, a.* FROM tb_Product a, (SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum, * FROM tb_Product WHERE isPassAudit='true' and pagerRank0>0 ) AS b WHERE b.pagerrank0 =a.pagerrank0 and b.releaseTime =a.releaseTime and b.productid=a.productid AND b.rownum BETWEEN 10 AND 20 ORDER BY b.rownum这个读page如何?
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。(11 行受影响)
表 'tb_Product'。扫描计数 12,逻辑读取 45 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。SQL Server 执行时间:
CPU 时间 = 16 毫秒,占用时间 = 2 毫秒。
CPU 时间 = 0 毫秒,占用时间 = 34 毫秒。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。SQL Server 执行时间:
CPU 时间 = 31 毫秒,占用时间 = 27 毫秒。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。(16 行受影响)
表 'tb_Product'。扫描计数 17,逻辑读取 20345 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。SQL Server 执行时间:
CPU 时间 = 156 毫秒,占用时间 = 180 毫秒。
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE --查看IO和Time
set statistics io on
set statistics time on SELECT b.rownum, a.*
FROM tb_Product a,
(SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum,
pagerrank0,releaseTime,productid
FROM tb_Product WHERE isPassAudit='true' and pagerRank0>0 ) AS b
WHERE b.pagerrank0 =a.pagerrank0 and b.releaseTime =a.releaseTime and b.productid=a.productid
AND b.rownum BETWEEN 159985 AND 160000
ORDER BY b.rownum
最后的运行结果如下:
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 31 毫秒,占用时间 = 56 毫秒。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。SQL Server 执行时间:
CPU 时间 = 16 毫秒,占用时间 = 13 毫秒。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。(16 行受影响)
表 'tb_Product'。扫描计数 17,逻辑读取 21768 次,物理读取 1 次,预读 22464 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。(1 行受影响)SQL Server 执行时间:
CPU 时间 = 281 毫秒,占用时间 = 9179 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
也就是总共用时:9秒
不知道你的测试环境的配置是什么,我的是双核2.2,3G内存的笔记本上测试的。而你的测试是1秒以内,怎么会有如此大的差异的?
和你机器的内存,cpu性能和使用情况(当前温度) 有关。
对于简单的t-sql写法,看io更有意义。继续关注。
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE --查看IO和Time
set statistics io on
set statistics time on
这个很容易证明:
比如你现在第一次执行:
select * from tbname
看一下io的读写,预读几乎等于逻辑读,这说明数据是从io上读取的.现在你
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
之后再select * from tbname
那么再看一下io的读写,预读应该远小于逻辑读,甚至为0,这说明
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
无法清除已缓存在内存中的数据。
DBCC DROPCLEANBUFFERS :
使用 DBCC DROPCLEANBUFFERS 测试包含冷缓存的查询,而不用关闭和重新启动服务器。
若要从缓冲池中删除清除缓冲区,请首先使用 CHECKPOINT 生成一个冷缓存。这可以强制将当前数据库的全部脏页写入磁盘,然后清除缓冲区。完成此操作后,便可发出 DBCC DROPCLEANBUFFERS 命令来从缓冲池中删除所有缓冲区。DBCC FREEPROCCACHE
使用 DBCC FREEPROCCACHE 清除过程缓存。释放过程缓存将导致系统重新编译某些语句(例如,即席 SQL 语句),而不重用缓存中的语句。这会导致查询性能暂时性地突然降低。之前在做调优时我也经常会使用这两个选项,事实上效果不明显。
to hyqok:你看这样优化试试呢?我这没数据假设productid 为主键且为聚集索引
再建一个非聚集索引
create index ix_01 on tb_Product(isPassAudit desc,pagerRank0 desc,releaseTime desc)那么先看一下,下面这个查询的io是多少?
SELECT * FROM (
SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum,
pagerrank0,releaseTime,productid FROM tb_Product WITH(index=ix_01)
WHERE isPassAudit='true' and pagerRank0>0
) AS B WHERE b.rownum BETWEEN 159985 AND 160000待测试结果。
表 'View_Product'。扫描计数 1,逻辑读取 490452 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
SELECT * FROM (
SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum,
pagerrank0,releaseTime,productid FROM tb_Product WITH(index=ix_01)
WHERE isPassAudit='true' and pagerRank0>0
) AS B WHERE b.rownum BETWEEN 159985 AND 160000
在建索引:
create index ix_01 on tb_Product(isPassAudit desc,pagerRank0 desc,releaseTime desc)
后,只读这个非聚集索引的page.
而且这个page是按照查询条件排过序的,理论上row_number()应该是很快的。手头上没有数据,以上只是推断。如果这样设置为了还是几W个page,我无语。