临时表上的 SQL 交叉联接结果缓慢

发布于 2024-12-29 00:03:04 字数 752 浏览 2 评论 0原文

已将以下代码添加到我的 SQL 查询中:(注意缩减版本)

DECLARE @rowType AS TABLE (
    rowTypeLabel NVARCHAR (20));

INSERT  INTO @rowType
VALUES ('Cumulative');

INSERT  INTO @rowType
VALUES ('Non-Cumulative');

--select * from @rowType


SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky CROSS JOIN @rowType
WHERE  (rowTypeLabel = 'Cumulative'
        OR (rowTypeLabel = 'Non-Cumulative'
            AND (EndDate IS NULL
                 OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

运行时间已从大约 10 分钟缩短到大约 1 小时,是否有人对为什么会出现这种情况有任何建议,没有此交叉联接的结果约为 46,000之后返回额外的 231 行(根据查询归类为“非累积”的任何内容。

Have added the following code to my SQL query: (Note cut down version)

DECLARE @rowType AS TABLE (
    rowTypeLabel NVARCHAR (20));

INSERT  INTO @rowType
VALUES ('Cumulative');

INSERT  INTO @rowType
VALUES ('Non-Cumulative');

--select * from @rowType


SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky CROSS JOIN @rowType
WHERE  (rowTypeLabel = 'Cumulative'
        OR (rowTypeLabel = 'Non-Cumulative'
            AND (EndDate IS NULL
                 OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

Run time has gone from around 10 minutes to around 1 hour, does anyone have any suggestions as to why this may be, the results without this cross join were around 46,000 and after brings back an additional 231 rows (anything that is classed as 'non-cumulative' as per query.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情深缘浅 2025-01-05 00:03:04

我猜这是一个非常简化的例子?所以我不能给你具体细节,但简单的答案是查询的累积部分比非累积部分做了更多的工作。

尝试这两个进行比较......

SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky

并且......

SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky
WHERE  EndDate IS NULL
       OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

我预计后者会花费更长的时间。

此外,对于优化器来说,合并多个业务逻辑的 OR 条件可能非常困难。这意味着以下结构可能更有效......

SELECT * FROM <non cumulative query>
UNION ALL
SELECT * FROM <cumulative query>

I'm guessing that this is a much simplified example? So I can't give you specifics, but the simple answer is that the cumulative part of the query is doing a lot more work than the non cumulative part.

Try these two for comparison...

SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky

And...

SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky
WHERE  EndDate IS NULL
       OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

The latter, I would expect, will take a lot longer.

Also, OR conditions to merge multiple pieces of business logic can be quite hard for the optimiser. This means that the following structure may be more efficient...

SELECT * FROM <non cumulative query>
UNION ALL
SELECT * FROM <cumulative query>
岛歌少女 2025-01-05 00:03:04

我不明白为什么你需要这里的 CROSS JOIN 构造——这只是让问题变得混乱。我将查询重写为:

SELECT ID, Name, StartDate, EndDate, 'Cumulative' AS Period
FROM   dbo.sicky
UNION ALL
SELECT ID, Name, StartDate, EndDate, 'Non-Cumulative' AS Period
FROM   dbo.sicky
WHERE EndDate IS NULL
    OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

应该是等价的,但更清楚地说明了您正在做什么。假设这个 UNION 的第一部分是您之前拥有的,而第二部分是缓慢的,则很可能 EndDate (或实际查询中的任何等效项)没有正确索引并导致过度扫描。发布您的执行计划以进行更详细的分析。

I don't see why you need the CROSS JOIN construct here -- it's just confusing the issue. I'd rewrite the query as this:

SELECT ID, Name, StartDate, EndDate, 'Cumulative' AS Period
FROM   dbo.sicky
UNION ALL
SELECT ID, Name, StartDate, EndDate, 'Non-Cumulative' AS Period
FROM   dbo.sicky
WHERE EndDate IS NULL
    OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

This should be equivalent, but illustrates what you are doing more clearly. Assuming the first part of this UNION is what you had before, and the second part is what is slow, it's likely that EndDate (or whatever the equivalent is in your real query) isn't indexed properly and is causing excessive scanning. Post your execution plans for more detailed analysis.

疑心病 2025-01-05 00:03:04

对于没有 JOIN 或子查询的简单 SELECT,10 分钟内 46000 行......这似乎太多了。检查您是否已在 StartDate 和 EndDate 上创建并启用索引。如果是这样,我同意民主党的答案。

46000 rows in 10 minutes for a simple SELECT with no JOIN or subqueries ... it seems too much. Check if you have created and enabled indexes on StartDate and EndDate. If so, I go with mwigdahl o Dems answers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文