SQL Server 中的“BETWEEN”函数是不是非常昂贵?

Posted

技术标签:

【中文标题】SQL Server 中的“BETWEEN”函数是不是非常昂贵?【英文标题】:Is the 'BETWEEN' function very expensive in SQL Server?SQL Server 中的“BETWEEN”函数是否非常昂贵? 【发布时间】:2011-04-07 14:18:29 【问题描述】:

我正在尝试将两个相对简单的表连接在一起,但我的查询遇到了严重的挂起。我不知道为什么,但我认为这可能与“之间”功能有关。我的第一个表看起来像这样(还有很多其他列,但这将是我要提取的唯一列):


RowNumber
1
2
3
4
5
6
7
8

我的第二个表将我的行“分组”为“块”,并具有以下架构:


BlockID     RowNumberStart     RowNumberStop
1           1                  3
2           4                  7
3           8                  8

我希望得到的期望结果是将 RowNumber 与 BlockID 链接起来,如下所示,与第一个表的行数相同。所以结果应该是这样的:


RowNumber   BlockID           
1           1
2           1
3           1
4           2
5           2
6           2
7           2 
8           3

为了得到它,我使用了以下查询,将结果写入临时表:


select A.RowNumber, B.BlockID
into   TEMP_TABLE
from   TABLE_1 A left join TABLE_2 B
on     A.RowNumber between B.RowNumberStart and B.RowNumberStop

TABLE_1 和 TABLE_2 实际上是非常大的表。表 1 大约有 122M 行,而 TABLE_2 大约有 65M 行。在 TABLE_1 中,RowNumber 被定义为“bigint”,而在 TABLE_2 中,BlockID、RowNumberStart 和 RowNumberStop 都被定义为“int”。不确定这会有所不同,但也只是想包含该信息。

查询现在已经挂了八个小时。对这种类型和数据量的类似查询不会花费这么长时间。所以我想知道它是否可能是挂起这个查询的'between'语句。

绝对欢迎任何有关如何提高效率的建议。

【问题讨论】:

你看过执行计划了吗? 之前从未在连接中使用过 【参考方案1】:

BETWEEN 只是 :

的简写
select A.RowNumber, B.BlockID
into   TEMP_TABLE
from   TABLE_1 A left join TABLE_2 B
on     A.RowNumber >= B.RowNumberStart AND A.RowNumber <= B.RowNumberStop

如果执行计划从 B 到 A(但左连接表明它必须从 A 到 B,真的),那么我假设 TABLE_1 是在 RowNumber 上索引的(这应该涵盖在这个查询中)。如果它只有 RowNumber 上的聚集索引并且表很宽,我建议只在 RowNumber 上使用非聚集索引,因为这样每页可以容纳更多的行。

否则,您希望在 RowNumberStart DESC 或 RowNumberStop ASC 上的 TABLE_2 上建立索引,因为对于给定的 A,您需要 RowNumberStart 上的 DESC 才能匹配。

我认为您可能希望将联接更改为 INNER JOIN,即设置联接条件的方式。 (您是否会立即获得 TABLE_1?)

如果您查看您的执行计划,您应该会获得更多关于为什么性能可能不好的线索,但在查找 TABLE_1 时可能没有使用停止条件。

不幸的是,SQLMenace 关于SELECT INTO 的回答已被删除。我对此的评论是:@Martin SELECT INTO 的性能不像以前那么糟糕,但我仍然建议将CREATE TABLE 用于大多数 生产,因为SELECT INTO 将推断类型和可空性。如果您验证它正在做您认为它正在做的事情,这很好,但是创建一个超长的 varchardecimal 具有非常奇怪的精度的列不仅会导致奇怪的表,而且会导致性能问题(尤其是一些当你忘记 LEFT 或其他什么时,那些大的 varchars)。我认为这有助于明确您对表格的期望。通常我会使用 WHERE 0 = 1 SELECT INTO 并检查架构,然后使用我的调整编写脚本(例如添加 IDENTITY 或添加带有默认时间戳的列)。

【讨论】:

内连接有意义,所以我将查询更改为内连接。另外,我按照你的建议使用了索引,查询运行了大约 20 分钟左右。非常感谢您的帮助!【参考方案2】:

您有一个主要问题:您想一次显示过多的数据量。您确定要一次处理表 1 中 ALL 122M 行的结果吗?你真的需要那个吗?

【讨论】:

他正在插入一个表格而不是从一个表格中选择

以上是关于SQL Server 中的“BETWEEN”函数是不是非常昂贵?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 索引如何帮助将 BETWEEN 用于给定查询

sql server BETWEEN and

从sql表里截取字符串中的日期

Datatypes translation between Oracle and SQL Server

SQL Server: Difference between PARTITION BY and GROUP BY

SQL Server 计算汉字笔画函数