mysql - 将我的 SQL 减少了 40%,但运行速度却慢了 60 倍?

标签 mysql sql hibernate jpa

我有 JPA 生成的 SQL,在最坏的情况下有 1250 行。

我的查询结构是嵌套在查询的 WHERE 语句中的 20 个子查询。此查询用时 0.015 秒。

我试图优化我的查询,因为我注意到我在子查询中重复使用了很多连接(例如,两个子查询的区别仅在于它们的 WHERE 语句)。这将 SQL 减少到 750 行和 12 个子查询,但由于某种原因,运行时间为 0.9 秒。

有什么可以解释的吗?当有更多可用数据时,我试图使查询运行得更快的尝试可能实际上运行得更快吗?

谢谢

最佳答案

根据问题中提供的有限信息,我只能推测具体情况下执行时间增加的确切原因,但总而言之,更少的代码并不等于更快的查询。

“简化”查询会导致执行时间更长的主要原因之一是简化意味着不再使用索引,因为虽然查询看起来更易于阅读,但实际上您是在要求优化器做一些更复杂的事情.

想象一下这个简单的模式:

CREATE TABLE T1 (ID INT AUTO_INCREMENT PRIMARY KEY, A INT);
CREATE TABLE T2 (ID INT AUTO_INCREMENT PRIMARY KEY, A INT, B INT);

CREATE INDEX IX_T2_A ON T2 (A);
CREATE INDEX IX_T2_B ON T2 (B);

现在,假设我有以下查询:

SELECT  COUNT(T1.ID)
FROM    T1
        INNER JOIN
        (   SELECT  ID
            FROM    T2
            WHERE   A IN (1, 10)
            UNION 
            SELECT  ID
            FROM    T2
            WHERE   B IN (1, 10)
        ) T2
            ON t2.ID = t1.ID;

您可能会想,这可以“简化”为删除 UNION,如下所示:

SELECT  COUNT(T1.ID)
FROM    T1
        INNER JOIN
        (   SELECT  ID
            FROM    T2
            WHERE   A IN (1, 10)
            OR      B IN (1, 10)
        ) T2
            ON t2.ID = t1.ID;

但是,通过组合您的标准,您已确保不会使用任何索引(在T2.AT2.B 上),因为优化器试图同时执行两者。因此,不是使用现有的两个索引,而是执行全表扫描,并且根据数据的分布,这可能会更加昂贵。

这在运行 EXPLAIN 时得到确认:

ID      SELECT_TYPE     TABLE       TYPE    POSSIBLE_KEYS   KEY     KEY_LEN     REF     ROWS    FILTERED    EXTRA
1       PRIMARY         <derived2>  system  (null)          (null)  (null)      (null)  1       100     
1       PRIMARY         T1          const   PRIMARY         PRIMARY     4       const   1       100         Using index
2       DERIVED         T2          index   IX_T2_A         IX_T2_A     5       (null)  1       100         Using where; Using index
3       UNION           T2          index   IX_T2_B         IX_T2_B     5       (null)  1       100         Using where; Using index
(null)  UNION RESULT    <union2,3>  ALL         (null)  (null)      (null)  (null)  (null)      (null)  


ID      SELECT_TYPE TABLE       TYPE    POSSIBLE_KEYS   KEY     KEY_LEN     REF     ROWS    FILTERED    EXTRA
1       PRIMARY     <derived2>  system  (null)          (null)  (null)      (null)  1       100     
1       PRIMARY     T1          const   PRIMARY         PRIMARY 4           const   1       100     Using index
2       DERIVED     T2          ALL     IX_T2_A,IX_T2_B (null)  (null)      (null)  1       100     Using where

Example on SQL Fiddle

关于mysql - 将我的 SQL 减少了 40%,但运行速度却慢了 60 倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21428814/

相关文章:

php - 如何根据用户互动/最感兴趣的用户对帖子进行排序

mysql - 从两列中选择不同的组合

java - 在 jpa 2.1 中使用 ManyToMany 时分离的实体

java - JPA/Hibernate 无法创建名为 Order 的实体

java - 插入新行,并通过简单计算增加最大值(并发问题)

mysql - EAV vs null vs 混合

mysql - 我可以在 SQL 的 WHERE 子句中使用 SUM 函数的结果吗?

使用 WHERE 子句的具有多个表的 MySQL UPDATE 语法

sql - 无法检索从 mysql 函数返回的值

MySQL COUNT 天数