2

我使用基于具有 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 字段上排序很快。按其他列过滤也很快。

4

5 回答 5

2

我知道这是一个非常古老的问题,但如果有人仍在寻找解决方案,你可以试试这个。我最近遇到了同样的问题,它是在一个相对简单的查询上,一个连接中只有 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 进行比较也非常快,所以我让它这样(它在报告中使用,比较值作为参数提供)

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

于 2017-08-25T07:58:06.487 回答
1

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

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

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

于 2009-01-22T10:59:17.307 回答
1

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

问题是,查询中的每个附加连接都会将可能的计划数量乘以不断增加的数量,导致随着连接数量的增加,要考虑的计划数量出现双因子(比指数更差)增长。出于这个原因,数据库必须将搜索限制在某个地方,这意味着对于涉及许多连接的查询,不可避免地会选择次优计划。

作为参考,PostgreSQL 默认在 12 次连接后停止评估所有可能的计划。SQL Server 肯定会有类似的限制。评估 17 个连接需要 (2 * 13) * (2 * 14) * (2 * 15) * (2 * 16) * (2 * 17) 次 - 这足以压倒任何具有曾经存在过,或将永远存在。

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

为什么需要加入 17 个表?有没有办法可以简化您的数据库架构?

于 2009-01-22T11:03:35.830 回答
1

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

myColumn = CAST(1 AS BIT)

CAST(myColumn AS BIT) = 1

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

于 2018-05-22T15:22:13.613 回答
1

慢的 :

select * from bigTable where column = 1

慢的

select * from bigTable where column = cast(1 as bit)

快速地 :

将@b 声明为位 = 1

select * from bigTable where column = @b

于 2019-09-18T17:41:41.700 回答