为什么加入CTE这么慢?

发布于 2025-01-23 19:26:24 字数 972 浏览 3 评论 0原文

我的查询看起来像这样

WITH 
events AS (
    SELECT * 
    FROM Table1 ae
    WHERE '2022-04-21 06:25:22' >= ae.Stamp
    AND ae.Stamp > '2022-04-21 05:25:22'
),
users AS 
(
    SELECT User,COUNT(*) AS cnt 
    FROM events 
    GROUP BY User
    HAVING cnt > 60
)
SELECT *
FROM events e join users u on e.User = u.User

,执行速度非常慢。执行两个CTE大约需要13秒,事件包含3009个记录,用户包含2个记录。但是,如图所示,运行查询需要超过30分钟:-O

如果我更改最后一行以明确比较用户表的用户表中

FROM events e join users u on e.User in ('User1','User2')

查询在22秒内执行!

为什么加入这么慢? 有没有更好的方法来实施查询?

谢谢

---更新---

基于SOS的输入,我将查询更改为

WITH 
events AS (
    SELECT *,
    COUNT(*) OVER(PARTITION BY User) AS TotalUser 
    FROM Table1 ae
    WHERE '2022-04-21 06:25:22' >= ae.Stamp
    AND ae.Stamp > '2022-04-21 05:25:22'
)
SELECT *
FROM events e 
WHERE TotalUser > 60

现在的执行时间为6s(在同一数据上):-)。

I have a query looking like this

WITH 
events AS (
    SELECT * 
    FROM Table1 ae
    WHERE '2022-04-21 06:25:22' >= ae.Stamp
    AND ae.Stamp > '2022-04-21 05:25:22'
),
users AS 
(
    SELECT User,COUNT(*) AS cnt 
    FROM events 
    GROUP BY User
    HAVING cnt > 60
)
SELECT *
FROM events e join users u on e.User = u.User

that executes extremely slow. Executing the two CTEs takes roughly 13s and events contains 3009 records, users contains 2 records. However running the query as shown takes more than 30 minutes :-O

If I change the last line to explicitly comparing the users from users table

FROM events e join users u on e.User in ('User1','User2')

the query executes in 22 seconds!

Why is the join so slow ?
Is there a better way to implement the query ?

Thanks

---update---

Based on the input from SOS I changed the query to

WITH 
events AS (
    SELECT *,
    COUNT(*) OVER(PARTITION BY User) AS TotalUser 
    FROM Table1 ae
    WHERE '2022-04-21 06:25:22' >= ae.Stamp
    AND ae.Stamp > '2022-04-21 05:25:22'
)
SELECT *
FROM events e 
WHERE TotalUser > 60

now with an execution time of 6s (on same data) :-).

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

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

发布评论

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

评论(2

转瞬即逝 2025-01-30 19:26:24

尝试创建此索引。

CREATE INDEX ts_user ON Table1 (Stamp, User)

它应该帮助日期范围的过滤器和组。

而且,如果您使用SSMS-Microsoft的SQL Server Management Studio-此提示适合您:在查询窗口中右键单击右键,然后选择“显示实际执行计划”,然后运行查询。执行计划显示有时建议创建新的索引。

Try creating this index.

CREATE INDEX ts_user ON Table1 (Stamp, User)

It should help both the date-range filter and the GROUP BY.

And, if you use SSMS -- Microsoft's SQL Server Management Studio -- this tip is for you: Right-click in a query window, then select Show Actual Execution Plan, then run the query. The execution plan display sometimes recommends a new index to create.

遗失的美好 2025-01-30 19:26:24

看看这是否有效:

SELECT u.*, ae.cnt
  FROM (
    SELECT User, COUNT(*) AS cnt
        FROM Table1
        WHERE Stamp >  '2022-04-21 05:25:22'
          AND Stamp <= '2022-04-21 05:25:22' + INTERVAL 1 HOUR 
        GROUP BY User
        HAVING cnt > 60
     ) AS ae
  JOIN Users AS u  USING(User)

可能的索引:

Table1:  INDEX(Stamp, User)
Users:   PRIMARY KEY(User) or INDEX(User), but not both

See if this works better:

SELECT u.*, ae.cnt
  FROM (
    SELECT User, COUNT(*) AS cnt
        FROM Table1
        WHERE Stamp >  '2022-04-21 05:25:22'
          AND Stamp <= '2022-04-21 05:25:22' + INTERVAL 1 HOUR 
        GROUP BY User
        HAVING cnt > 60
     ) AS ae
  JOIN Users AS u  USING(User)

Possible indexes:

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