(似乎更新表和索引的统计信息来解决这个问题)

这个问题困扰了我一段时间,项目中经常会出现很奇怪的情况:如果查询数据库有结果返回,查询过程会非常快;但是如果没有结果,很可能会执行很长一段时间以致超时。今天又遇到了这种情况而且今天还算有时间,我就认真跟踪了一下,发现有数据时,执行计划显示index seek,而没有数据返回时,执行计划显示的是Table scan,我对执行计划认真分析比对,感觉找到了其中的原因。

一般好一点的数据库系统都比较智能,他会有一套规则来判断如何执行查询会比较快。对于索引有一个规则是如果join返回的结果数量比较少,查询引擎会选择使用索引来加快速度,但是如果结果数量非常多,应用索引会耗费更多的资源和时间,查询引擎会选择表扫描。而选择执行计划的过程也是会耗费时间的,如果这个过程太长也是会影响查询速度的,所以一般分析引擎只是大概进行估计,在数据量很大的情况下很容易出现误差,而我的问题就是分析引擎的误差引起的。

我的查询涉及到table A(13亿多条数据),B(临时表,几百到几十万条数据)和其他几个几百几千几万的小表,A和B是需要join的,如果B的数据量很大,数据库需要分析的时间就会很多,特别是与A关联后没有结果返回的时候,我想数据库设计者不知是出于什么考虑,反正结果是选择表扫描。

 我后来的方案做了一个循环,B表每次取1000条数据与A关联,最后将结果放入一个表中,速度飞快


又碰到另外一种情况,也是大数据量执行超时,查看一下执行计划超大表A总是会先与小表C关联,造成表扫描和不能应用索引。我尝试使用嵌套查询让A和B先关联,但是SQL在执行的时候还是会按照自己的分析让A和C先关联,最后我不得不利用临时表,把它拆成两个SQL,这样牺牲点内存,SQL终于按我的意愿执行了,速度也是飞快。

 

似乎用with index来强制使用索引更好一些,现在用with index表还不能使用别名。(select * from table with(index =index1) inner join table2 on...)

如果一个列有很多重复行,建立索引后效率也会很低,可以考虑根据情况建立联合索引。

select ... from A

inner join B on  A.c1=B.c1

innerjoin C on A.c2=C.c2

上面的情况可以应用A(c1,c2)联合索引。

posted on 2009-05-12 17:39  风生水起  阅读(638)  评论(1编辑  收藏  举报