查询缓慢的INFORMATION_SCHEMA

我们有一个.NET Windows应用程序,它在login时运行以下查询来获取有关数据库的一些信息:

SELECT t.TABLE_NAME, ISNULL(pk_ccu.COLUMN_NAME,'') PK, ISNULL(fk_ccu.COLUMN_NAME,'') FK FROM INFORMATION_SCHEMA.TABLES t LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk_tc ON pk_tc.TABLE_NAME = t.TABLE_NAME AND pk_tc.CONSTRAINT_TYPE = 'PRIMARY KEY' LEFT JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE pk_ccu ON pk_ccu.CONSTRAINT_NAME = pk_tc.CONSTRAINT_NAME LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk_tc ON fk_tc.TABLE_NAME = t.TABLE_NAME AND fk_tc.CONSTRAINT_TYPE = 'FOREIGN KEY' LEFT JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE fk_ccu ON fk_ccu.CONSTRAINT_NAME = fk_tc.CONSTRAINT_NAME 

通常这会在几秒钟内运行,但是在一台运行SQL Server 2000的服务器上运行需要四分钟的时间。 我启动了执行计划后运行它,结果很大,但是这部分引起了我的注意(它不会让我发布图像):

http://img35.imageshack.us/i/plank.png/

然后我更新了执行计划中提到的所有表格的统计数据:

 update statistics sysobjects update statistics syscolumns update statistics systypes update statistics master..spt_values update statistics sysreferences 

但是这并没有帮助。 索引调整向导也没有帮助,因为它不让我select系统表。 这个服务器上没有别的东西在运行,所以别的什么都不会放慢速度。 我还能做些什么来诊断或修复该服务器上的问题?

如果情况许可,左连接在生成大量logging集方面是臭名昭着的。 我偶尔遇到这样的问题,我没有一个快速,简单的答案。 我发现玩弄查询,例如一次build立一个查询,是解决哪个连接问题的最好方法。

你有没有尝试从查询中的表中select计数(*),看看他们之一是否有意外的高数字行?

JR

更多的想法:到目前为止还不清楚问题在于服务器还是如果查询是病态的并且会杀死任何服务器。 我想你可以将数据库复制到不同的服务器,然后再次尝试查询。

如何修改查询是这样的:

 SELECT t.TABLE_NAME, ISNULL(pk_ccu.COLUMN_NAME,'') PK, ISNULL(fk_ccu.COLUMN_NAME,'') FK FROM INFORMATION_SCHEMA.TABLES t LEFT JOIN ( INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk_tc INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE pk_ccu ON pk_ccu.CONSTRAINT_NAME = pk_tc.CONSTRAINT_NAME ) ON pk_tc.TABLE_NAME = t.TABLE_NAME AND pk_tc.CONSTRAINT_TYPE = 'PRIMARY KEY' LEFT JOIN ( INFORMATION_SCHEMA.TABLE_CONSTRAINTS fk_tc INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE fk_ccu ON fk_ccu.CONSTRAINT_NAME = fk_tc.CONSTRAINT_NAME ) ON fk_tc.TABLE_NAME = t.TABLE_NAME AND fk_tc.CONSTRAINT_TYPE = 'FOREIGN KEY' 

我认为内部联接应该是安全的,因为tc和ccu表应该有匹配的logging。 以这种方式进行查询是否可以缩短执行时间?

你有没有检查你是否被阻止?

既然你已经深入了解执行计划,我猜你已经有了,但是总是值得一提的。 根据您运行的隔离级别以及系统上正在运行的其他活动,您可能正在等待locking。

桌子可以高度分散吗?

您可以在SQL 2000(不是SQL 2005或更高版本)上检查系统表的碎片。 请参阅Kalen Delaney关于系统表碎片的博客条目 ,以获取更多信息。 (但是,如果表格不是很大的话,高度的碎片化程度可能会引起误解,我通常使用1K页作为一个经验法则。)

SQL实例是否有更大的性能问题?

我真的不确定这个问题是否是这里的计划 – 从这个链接看起来你有一个强有力的联接计划,但是如果实际上很less的行被返回,那么我不认为这些联接会使性能很糟糕除非你有其他问题。 我曾经看过很多高估了排行榜的计划,并且performance得很好,这是低估的排名,通常会杀了我。 (如果其他人知道这可能是不正确的情况下,我很想听到他们!)

在这一点上,我个人会做一个快速检查框中的SQL环境,以确保事情看起来如我所料。 我经常发现“为什么这个查询很慢”这些问题导致发现有一个更大的性能问题。

  1. sp_configure选项,如maxdop,内存最小/最大值,locking设置
  2. 请检查SQL错误日志是否有任何有关磁盘延迟的警告,确保在启动时能够使用大页面,如果我期望它使用大页面等
  3. 定期安排在正常时间范围内完成的SQL作业?
  4. 检查你收集的任何性能计数器,看它们是否在正常范围内。

只是一个想法,SQL 2000中的优化器引擎曾经很难尝试为超过4个内部连接的语句find最优化的查询计划,而且我认为左连接更加困难。

正如你在你提供的quereplan中看到的,它执行了多对多的查询。

SQL 2000的最佳实践是,如果您需要来自4个以上的表的数据,则可以分解代码。

/HåkanWinther

这可能与您遇到的问题有关

http://bugs.mysql.com/bug.php?id=19588