将BIT列与0而不是1进行比较时,查询的工作速度会慢几倍

时间:2009-01-22 10:30:19

标签: sql-server performance bit

我使用基于具有17个连接(内部和左/右外部)和子查询的复杂查询的视图。所有视图行都在大约5秒内显示。

SELECT * FROM a_view;

其中一个视图列的类型为BIT。当我过滤与1比较的视图行时,查询再次工作大约5秒。

SELECT * FROM a_view WHERE c = 1;

但是当我将这个BIT列与0进行比较时,查询的工作时间约为50秒(慢10倍)。

SELECT * FROM a_view WHERE c = 0;

返回相同结果行的此查询按预期工作大约10秒:

SELECT * FROM a_view 
EXCEPT
SELECT * FROM a_view WHERE c = 1;

所以我想知道为什么比较0或'FALSE'需要这么多时间?请问任何想法。

对此BIT字段进行排序很快。其他列过滤也很快。

5 个答案:

答案 0 :(得分:1)

SQL Server sql引擎将视图的整个SQL查询放在您在视图上编写的SQL语句中,然后尝试对其进行优化。

这可能会导致c = 0的情况,所用表的统计信息显示与该谓词匹配的行多于c = 1。例如,在c = 1的情况下,包含作为连接中心的c字段的表可能只返回5个匹配行,这导致执行计划与表返回100万行(例如, c = 0的情况。

因此,检查两者的执行计划。同时检查两者的服务器分析器结果,与c = 0一样,可能有比c = 1更多的读取,并且返回的结果比c = 1多得多。返回所有行可能需要一段时间,所以这也可能是查询速度较慢的原因。

答案 1 :(得分:1)

通常,有多种方法可以执行涉及连接的查询。所有现代RDBMS都会搜索不同的连接计划,通过估算每个计划的成本(CPU和磁盘访问时间)来寻找最佳计划。

问题是,查询中的每个额外联接都会将可能计划的数量乘以一个递增的数字,从而导致计划数量双因素(比指数级别增长)增长连接数增加。出于这个原因,数据库必须在某处限制搜索,这意味着对于涉及许多连接的查询,不可避免地会选择次优计划。

作为参考,默认情况下,PostgreSQL在12个连接后停止评估所有可能的计划。 SQL Server肯定会有类似的限制。 17个连接将花费(2 * 13)*(2 * 14)*(2 * 15)*(2 * 16)*(2 * 17)倍的时间进行评估 - 它足以压倒任何有RDBMS的RDBMS曾经存在,或永远

还有一个事实是,DB会根据粗略统计数据估算成本,例如列中不同值的数量和/或列中10个最常见值的列表。这一切加起来的事实是,随着联接数量的增加,选择最佳(甚至是合理的)联接策略的可能性将向下

为什么你需要加入17个桌子?你有没有办法简化数据库架构?

答案 2 :(得分:1)

我知道这是一个非常古老的问题,但如果有人还在寻找解决方案,你可以试试这个。我最近遇到了同样的问题,它是一个相对简单的查询,只有3个连接表,其中最大的只有1000多行。不幸的是,我没有权限查看执行计划,所以我不得不即兴发挥。

select * from subquery_x;

非常快,基本上立即完成(返回大约500行),因为它应该

select * from subquery_x where column_x = 1  

dtto,非常快,column_x是一个非空位列

select * from subquery_x where column_x = 0
select * from subquery_x where column_x != 1

应该返回大约300行,两者都非常非常慢,实际上花了几分钟!!

简单(但很奇怪)解决方案 - 将where子句中的列转换为tinyint

select * from subquery_x where convert(tinyint,column_x) = 0

我知道这可能会产生一些性能副作用,但它的作用就像魅力一样,将转换后的列值与1进行比较的速度也非常快,所以我就这样说了(它用于提供比较值的报告中)作为参数)

如果有人知道为什么会发生这种情况,请告诉我们,我怀疑这是一个错误,但谁知道,这可能是一个令人讨厌的功能: - )

答案 3 :(得分:0)

horcic.roman的解决方案类似...我将值或列转换为BIT以大幅提高速度。

myColumn = CAST(1 AS BIT)

CAST(myColumn AS BIT) = 1

显然很奇怪,因为该列是BIT NOT NULL。

答案 4 :(得分:0)

慢:

从bigTable中选择*,其中column = 1

从bigTable中选择*,其中column = cast(1位)

快速:

将@b声明为bit = 1

从bigTable中选择*,其中column = @b