简体   繁体   English

单独运行时查询速度快,但在连接内添加时查询速度慢

[英]Query fast when run separately but slow when added inside a join

In SQL Server, this query runs very fast, less than a second:在 SQL 服务器上,这个查询运行的非常快,不到一秒:

SELECT T1.id
FROM first AS T1
WHERE T1.id = 21

This query also runs very fast, less than a second, even though it has 53 million records but only has about six records for id 21:这个查询也运行得非常快,不到一秒,尽管它有 5300 万条记录,但 id 21 只有大约 6 条记录:

SELECT TOP 1 T2.value
FROM second AS T2 WITH(INDEX(IX_second))
WHERE T2.id = 21 
  AND T2.b = 1 
  AND T2.c = 0 
  AND T2.d = 0 
  AND T2.e = 0
ORDER BY T2.id, T2.b, T2.c, T2.d, T2.e, T2.timestamp DESC

However, this query, where I replace the 21 in the inner SELECT with T1.id, is very, very slow, more than 80 seconds:但是,我用 T1.id 替换内部SELECT中的 21 的这个查询非常非常慢,超过 80 秒:

SELECT T1.id, T3.value
FROM first AS T1
JOIN second AS T3 ON T3.id IN (SELECT TOP 1 T2.id
                               FROM second AS T2 WITH(INDEX(IX_second))
                               WHERE T2.id = T1.id 
                                 AND T2.b = 1 
                                 AND T2.c = 0 
                                 AND T2.d = 0 
                                 AND T2.e = 0
                               ORDER BY T2.id, T2.b, T2.c, T2.d, T2.e, T2.timestamp DESC)
 WHERE T1.id = 21

Why would this query take so very long and how do I make it faster?为什么这个查询会花这么长时间,我该如何让它更快?


Edit: Here is the plan, with some table and field names changed to protect the innocent:) brentozar.com/pastetheplan/?id=rJYBSfwws编辑:这是计划,更改了一些表和字段名称以保护无辜者:) brentozar.com/pastetheplan/?id=rJYBSfwws

All depends on the way the DBMS is computing the data.一切都取决于 DBMS 计算数据的方式。 But in this case 53M is going to be processed (T1 X T3) Times.但在这种情况下,将要处理 53M (T1 X T3) 次。 And each time there is going to do order, reverse, query, and possibly some join with source table if the index was not build with values (b,c,d,e...).如果索引不是用值构建的(b,c,d,e ...),每次都会进行排序,反向,查询以及可能与源表的一些连接。

I don't get the logic of your query.我不明白你的查询逻辑。 Why not use just one join...为什么不只使用一个连接...

SELECT T1.id, T3.value
  FROM first AS T1
  JOIN second AS T2 ON T1.id = T2.id 
 WHERE T1.id = 21 
  AND T2.b = 1 AND T2.c = 0 AND T2.d = 0 AND T2.e = 0

This looks to have se same result as the above.这看起来与上面的结果相同。

Using sub-queries inside an IN() statement is syntactically ok, but I don't recommend it, as they are a slow way of managing JOINs between tables.IN()语句中使用子查询在语法上是可以的,但我不推荐它,因为它们是管理表之间 JOIN 的缓慢方式。

As per others have suggested, use a temporary table .按照其他人的建议,使用临时表 Even a CTE() in my view is at least a cleaner version of the code and much easier to understand.在我看来,即使是 CTE() 也至少是代码的更简洁版本并且更容易理解。 You also need to study your execution plan.您还需要研究您的执行计划。

I've not tested this, but try something like:我没有测试过这个,但尝试类似的东西:

    SELECT TOP 1 T2.id
    INTO #tblTEMP1
    FROM second AS T2 
    WHERE T2.b = 1 
      AND T2.c = 0 
      AND T2.d = 0 
      AND T2.e = 0
    ORDER BY T2.id, T2.timestamp DESC
..
..
    SELECT T1.id, T3.value
    FROM first AS T1
    INNER JOIN #tblTEMP1 AS t ON t.ID = t1.ID
    INNER JOIN second AS T3 ON T3.id = t.ID
    WHERE T1.id = 21

I bet this will be faster, but perhaps not as fast as you'd expect.我敢打赌这会更快,但可能没有您预期的那么快。

Again, you need to study your execution plan each case and determine the exact bottle-neck(s) and place INDEXes where necessary.同样,您需要研究每个案例的执行计划并确定确切的瓶颈并在必要时放置INDEXes

This looks like a case where CROSS APPLY can be used.这看起来像是可以使用CROSS APPLY的情况。 This allows the TOP 1 and ORDER BY , but would avoid a double reference to the second table.这允许TOP 1ORDER BY ,但会避免对second表的双重引用。

Try:尝试:

SELECT T1.id, T3.value
FROM first AS T1
CROSS APPLY (
    SELECT TOP 1 T2.*
    FROM second AS T2 --WITH(INDEX(IX_second))
    WHERE T2.id = T1.id 
    AND T2.b = 1 
    AND T2.c = 0 
    AND T2.d = 0 
    AND T2.e = 0
    ORDER BY T2.id, T2.b, T2.c, T2.d, T2.e, T2.timestamp DESC
) T3
WHERE T1.id = 21

If IX_second is an index on second(id) , it is likely that the SQL server query optimizer will select that index without the need for an index hint.如果IX_secondsecond(id)上的索引,则 SQL 服务器查询优化器很可能会 select 该索引而不需要索引提示。

Just to check: Are you sure you mean T2.id = T1.id and not something like T2.first_id = T1.id ?只是为了检查:你确定你的意思是T2.id = T1.id而不是像T2.first_id = T1.id这样的东西吗?

One more note: Since T2.id, T2.b, T2.c, T2.d, T2.e will all be fixed in the CROSS APPLY results, you can likely drop them from the ORDER BY clause.请注意:由于T2.id, T2.b, T2.c, T2.d, T2.e都将固定在CROSS APPLY结果中,因此您可以将它们从ORDER BY子句中删除。

ADDENDUM: Based on the query from your posted execution plan, the above would be equivalent to:附录:根据您发布的执行计划中的查询,以上内容等同于:

SELECT *
FROM Event_Item AS ei
CROSS APPLY (
    SELECT TOP 1 eisp1.*
    FROM Event_Item_Spread AS eisp1
        -- WITH(INDEX(IX_Event_Item_Spread__event_item__sportsbook__period__ingame__alt__timestamp_desc))
    WHERE eisp1.event_item_id = ei.id
      AND eisp1.sportsbook_id = 1
      AND eisp1.period = 0
      AND eisp1.in_game = 0
      AND eisp1.alt = 0
    ORDER BY eisp1.timestamp DESC
) AS eisp
WHERE ei.id = 39604314

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 两个查询分开很快,当作为子查询加入时很慢 - Two queries are fast separately, slow when joined as subqueries 优化在两个单独的步骤中运行时快速的慢速SQL查询 - Optimize slow SQL Query that's fast when run in two separate steps SQL子查询的运行速度非常快,但是在select中使用时非常慢 - SQL Sub-query run's very fast individually, but when used in select is very slow 声明表并加入表时,使用实数时显示缓慢但快速 - Declare table and join it shows slow, but fast when using real number 加入时Oracle查询速度慢,拆分成两个查询时速度快 - Oracle query slow when joining, fast when splitted into two queries 使用sp_executesql运行时的相同SQL查询是快速的,如果在查询分析器中作为动态查询执行,速度非常慢,为什么? - Same SQL query when run with sp_executesql is fast, very slow if executed as dynamic query in query analyser, why? 使用ORDERBY时MySQL慢速JOIN查询 - MySQL Slow JOIN query when using ORDERBY 使用 count(*) 和内连接时查询慢 - Query slow when use count(*) and inner join 添加 JOIN 时 BigQuery 查询速度极慢 - BigQuery query extremely slow when adding JOIN 两个独立的Oracle View运行速度很快,但结合起来却非常慢 - Two independent Oracle Views run fast but are extremely slow when combined
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM