SQL TOP 5000比正常查询更快,结果行少于5000?
我注意到一些奇怪的行为:
运行此查询: SELECT TOP 5000 t1.f1,t1.f2,t1.f3 FROM t1 JOIN t2 on t1.f1 = t2.f1 WHERE t2.f1 IS NOT NULL AND (t1.f5 != t2.f3) 在2秒内结果为3447行. 运行这一个: SELECT t1.f1,t1.f3 FROM t1 JOIN t2 on t1.f1 = t2.f1 WHERE t2.f1 IS NOT NULL AND (t1.f5 != t2.f3) 永远跑,直到我停止(至少120分钟!!). 表t1和t2保存大约500k条记录. 我总是认为TOP声明并不重要,如果总行数低于该数字,然而似乎有很大的差异.这是正常的(如果是这样,为什么)还是这只是一个侥幸? 编辑: 按照要求: T1: CREATE TABLE [dbo].[t1]( [f1] [int] NOT NULL,[f2] [varchar](10) NULL,[f3] [varchar](4) NULL,[f4] [int] NOT NULL,[f5] [varchar](max) NULL,CONSTRAINT [PK_t1] PRIMARY KEY CLUSTERED ( [f1] ASC )WITH (PAD_INDEX = OFF,STATISTICS_NORECOMPUTE = OFF,IGNORE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] F2: CREATE TABLE [dbo].[t2]( [f1] [nchar](10) NOT NULL,[f2] [nchar](10) NOT NULL,[f3] [varchar](max) NOT NULL,[f4] [nchar](10) NULL,[f5] [date] NULL,[f6] [date] NULL,[f7] [nchar](1) NULL,CONSTRAINT [PK_t2] PRIMARY KEY CLUSTERED ( [f1] ASC )WITH (PAD_INDEX = OFF,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 执行计划: 顶部: 没有顶部: 看这个,我必须得出结论,排序(为什么这样做)导致延迟…你会同意吗? 编辑2:根据要求,执行计划与循环选项没有顶部: 解决方法问题是,您的两个表[t1]和[t2]与JOIN列f1完全不同(并且很大程度上是不兼容的)数据类型.这使得查询优化器无法生成在两个500,000行表之间匹配多少行的准确估计.似乎使用默认的“猜测”,在这种情况下,实际数字的总体估计值(3477).因此,当您不使用TOP时,它认为排序,然后合并行(O(NLogN))比嵌套循环(O(N ^ 2))更有效,因为它是没有意识到(合并)JOIN实际上会消除几乎所有的行. 当您拥有TOP 5000时,它意识到嵌套循环更好,因为它将被切断不超过5000(远小于500k ^ 2,甚至小于500k * Log(500k)).但与嵌套循环不同,“合并排序”不能逐步完成,因此必须先对排序进行排序.所以在5000以下的输出将不会拯救你,所以嵌套循环显然是更好的选择(即使是坏的JOIN估计). 这里的根本问题是列T2.f1是一个NCHAR(10),对于看起来像它应该包含一个整数的东西来说,这是一个非常糟糕的选择.最佳的解决方案是将该列的数据类型更改为INT. 如果由于某种原因您不能这样做,那么根据您的SQL Server版本,您可以通过添加计算INT转换值[f1]的持久计算列来结束运行,然后在该值上引用兼容索引.这将允许索引和统计信息再次工作,这样的查询. 作为最后的手段,您还可以使用查询提示.我通常不推荐他们,因为他们往往是后来发生问题的停滞解决方案.但是,如果您觉得这是您唯一的选择,则将OPTION(FAST 1000)添加到您的查询结尾可能会起作用. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |