在视图View_Product表中有大约50万的纪录,现在要求对该表进行分页显示,代码如下:
SELECT *
FROM (SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum,
*
FROM view_product WHERE isPassAudit='true' and pagerRank0>0 ) AS D
WHERE isPassAudit='true' and pagerRank0>0 AND rownum BETWEEN 159985 AND 160000 ORDER BY pagerrank0 DESC,releaseTime desc其中记录集是数据库中第159985到160000条的纪录,我已经对视图View_product中建立了pagerrank0,releasetime的联合降序索引。
但这个SQL语句的执行效率还是比较低,并且跟所访问的纪录范围有关,越是后面的纪录,执行的速度越慢。
我通过set staticstic io on 查看了执行的信息,显示如下:
(16 行受影响)
表 'View_Product'。扫描计数 1,逻辑读取 518171 次,物理读取 1140 次,预读 47800 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
并且发现要读取的纪录越往后,逻辑读取的次数越多。
但是同样的SQL语句,在第二次进行运行时,运行的效率大幅度提高,显示的信息如下:
(16 行受影响)
表 '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,
*
FROM view_product WHERE isPassAudit='true' and pagerRank0>0 ) AS D
WHERE isPassAudit='true' and pagerRank0>0 AND rownum BETWEEN 159985 AND 160000 ORDER BY pagerrank0 DESC,releaseTime desc其中记录集是数据库中第159985到160000条的纪录,我已经对视图View_product中建立了pagerrank0,releasetime的联合降序索引。
但这个SQL语句的执行效率还是比较低,并且跟所访问的纪录范围有关,越是后面的纪录,执行的速度越慢。
我通过set staticstic io on 查看了执行的信息,显示如下:
(16 行受影响)
表 'View_Product'。扫描计数 1,逻辑读取 518171 次,物理读取 1140 次,预读 47800 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
并且发现要读取的纪录越往后,逻辑读取的次数越多。
但是同样的SQL语句,在第二次进行运行时,运行的效率大幅度提高,显示的信息如下:
(16 行受影响)
表 'View_Product'。扫描计数 1,逻辑读取 490452 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。请大家帮忙看下,看主要的问题所在
第二次是因为系统缓存了执行计划 会比第一次快
在前面的查询表中已经指定了,
加了索引还这么慢????
(
SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum, * FROM view_product WHERE isPassAudit='true' and pagerRank0>0
) AS D
WHERE rownum BETWEEN 159985 AND 160000
ORDER BY pagerrank0 DESC , releaseTime desc
需要对pagerrank0,releaseTime加索引.
你在查询条件字段加索引试试。
FROM (SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum,
*
FROM view_product WHERE isPassAudit='true' and pagerRank0>0 ) AS D
WHERE rownum BETWEEN 159985 AND 160000 ORDER BY rownum
应该和你的意思差不多吧
SELECT *
FROM (SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum, *
FROM view_product) AS D
WHERE isPassAudit='true' and pagerRank0>0 AND rownum BETWEEN 159985 AND 160000 如果纯粹从语句优化的角度,应该将子查询的结果放入中间表,在表上为 rownum 建聚集索引。
执行计划:
显示的信息:
如果可能应该将其放入临时表,在表上对 rownum 列键聚集索引,可以大大提升查询速度。
但是,如果你不打算反复执行这样的查询,就没有必要这么做了。
FROM view_product 这个子查询是全表全字段查询 ,因为要分页,不用临时表的话全表查询无法避免,优化的空间就在全字段上,我推测你占用1个G的内存字段不会少,先查询出主键记录,然后和主表做关联查询。自己先测试一下吧。如果第1次的查询还在5s以上就联系我吧。
因为视图和索引一起的话,索引会有小几率失效的。
如果能把视图去掉用原sql的话,可以试下 看看
WHERE rownum BETWEEN 159985 AND 160000 AND isPassAudit='true' and pagerRank0>0 ORDER BY pagerrank0 数据效果最高的那个条件要放到左边,对sql来说,oracle是从右到左
SELECT b.rownum,a.*
FROM view_product a,
(SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum,
pagerrank0,releaseTime
FROM view_product WHERE isPassAudit='true' and pagerRank0>0 ) AS b
WHERE b.pagerrank0=a.rownum and b.releaseTime=a.releaseTime
AND b.rownum BETWEEN 159985 AND 160000
ORDER BY b.rownum
消息 207,级别 16,状态 1,第 6 行
列名 'rownum' 无效。
FROM view_product a,
(SELECT ROW_NUMBER() OVER(ORDER BY pagerrank0 DESC,releaseTime desc) AS rownum,
pagerrank0,releaseTime
FROM view_product WHERE isPassAudit='true' and pagerRank0>0 ) b
WHERE b.pagerrank0=a.rownum and b.releaseTime=a.releaseTime
AND b.rownum BETWEEN 159985 AND 160000
ORDER BY b.rownum
pagerrank0,releaseTime
FROM view_product WHERE isPassAudit='true' and pagerRank0>0 生成临时表 ,在rownum上聚集的话 会更好,如前面那位仁兄说的。
调整一下你的业务逻辑..
就是你是否需要查这么后的记录..
像google啥的..一般我们输入了关键字查找后.我们只会关注前几页.或者前20页吧.
后面的.我们基本不感兴趣...