MySQL:超慢SQL

时间:2011-06-13 22:53:01

标签: mysql sql

我的查询执行时间差不多是8秒。我在查询上做了EXPLAIN,但我不知道如何解释结果。有人可以帮我解决这个问题吗?以下是EXPLAIN

的结果
===============================================================================================================================================================================================
| id | select_type        | table                 | type    | possible_keys        | key             | key_len | ref                                     | rows | Extra                       | 
===============================================================================================================================================================================================
| 1  | PRIMARY            | <derived2>            | ALL     | (NULL)               | (NULL)          | (NULL)  | (NULL)                                  | 669  | Using filesort              | 
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 2  | DERIVED            | Workflow              | const   | PRIMARY              | PRIMARY         | 4       |                                         | 1    | Using index                 | 
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 2  | DERIVED            | DataSource            | ref     | PRIMARY,WorkflowId   | WorkflowId      | 4       |                                         | 1546 | Using where                 | 
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 2  | DERIVED            | ReadyLog              | ALL     | DataSourceId         | (NULL)          | (NULL)  | (NULL)                                  | 9463 |                             | 
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 2  | DERIVED            | DataSourceActivityLog | eq_ref  | PRIMARY,DataSourceId | PRIMARY         | 4       | func                                    | 1    | Using where                 | 
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 2  | DERIVED            | User                  | eq_ref  | PRIMARY              | PRIMARY         | 4       | my_db.DataSourceActivityLog.UserId      | 1    |                             | 
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 3  | DEPENDENT SUBQUERY | DataSourceActivityLog | ref     | DataSourceId         | DataSourceId    | 4       | my_db.DataSource.Id                     | 1135 | Using where; Using filesort |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

如果您需要我提供其他信息,请告知我们。感谢。

更新1:丑陋的查询:

SELECT WrappedData.*
FROM   (SELECT DataSource.Id,
               DataSourceActivityLog.Description,
               DataSourceActivityLog.UserId,
               DataSource.Status    AS StatusCode,
               ( CASE
                   WHEN User.Name IS NULL THEN 'System'
                   ELSE User.Name
                 END )              AS `Username`,
               ReadyLog.`Timestamp` AS `Received`,
               DataSourceActivityLog.`Timestamp`
        FROM   DataSource
               LEFT JOIN DataSourceActivityLog AS ReadyLog
                 ON ( ( ReadyLog.DataSourceId = DataSource.Id
                        AND ReadyLog.Description = 'ready' )
                       OR ( ReadyLog.DataSourceId = DataSource.RootId
                            AND ReadyLog.Description = 'ready' ) ),
               DataSourceActivityLog
               LEFT JOIN USER
                 ON USER.Id = DataSourceActivityLog.UserId,
               Workflow
        WHERE  DataSource.Id IN ( 138, 139, 140, 141,
                                  142, 143, 144, 145,
                                  146, 147, 148, 149,
                                  150, 151, 152, 153,
                                  154, 155, 156, 157,
                                  158, 160, 162, 163,
                                  166, 167, 169, 170,
                                  171, 173, 174, 176,
                                  177, 179, 180, 182,
                                  183, 185, 186, 187,
                                  189, 190, 191, 193,
                                  194, 196, 197, 199,
                                  200, 201, 203, 204,
                                  207, 208, 209, 211,
                                  212, 214, 216, 217,
                                  219, 221, 222, 223,
                                  226, 227, 228, 231,
                                  232, 233, 235, 237,
                                  238, 242, 243, 240,
                                  245, 246, 248, 250,
                                  252, 253, 255, 256,
                                  258, 259, 261, 263,
                                  264, 266, 267, 271,
                                  269, 272, 276, 274,
                                  277, 280, 282, 284,
                                  279, 287, 285, 288,
                                  290, 291, 293, 298,
                                  301, 299, 303, 304,
                                  306, 309, 310, 311,
                                  315, 316, 318, 322,
                                  323, 325, 329, 330,
                                  331, 336, 339, 343,
                                  345, 346, 348, 351,
                                  352, 354, 356, 357,
                                  358, 360, 362, 364,
                                  367, 369, 370, 373,
                                  375, 376, 378, 381,
                                  382, 384, 386, 388,
                                  390, 391, 394, 395,
                                  397, 400, 402, 404,
                                  405, 408, 412, 413,
                                  414, 415, 420, 421,
                                  424, 425, 429, 430,
                                  433, 434, 438, 439,
                                  441, 442, 443, 445,
                                  446, 447, 449, 451,
                                  452, 453, 456, 457,
                                  458, 459, 462, 464,
                                  465, 466, 470, 473,
                                  474, 475, 477, 478,
                                  481, 482, 483, 485,
                                  487, 488, 489, 491,
                                  493, 494, 495, 497,
                                  498, 500, 501, 502,
                                  504, 505, 507, 508,
                                  509, 512, 513, 514,
                                  515, 516, 518, 519,
                                  520, 521, 522, 524,
                                  525, 526, 527, 529,
                                  530, 531, 532, 534,
                                  535, 536, 537, 539,
                                  540, 541, 542, 544,
                                  545, 546, 547, 549,
                                  550, 551, 552, 553,
                                  554, 556, 557, 559,
                                  560, 561, 562, 564,
                                  565, 566, 568, 569,
                                  570, 571, 572, 574,
                                  575, 576, 577, 579,
                                  580, 581, 582, 583,
                                  585, 586, 587, 588,
                                  590, 591, 592, 593,
                                  594, 596, 597, 598,
                                  599, 601, 602, 603,
                                  604, 606, 607, 608,
                                  609, 611, 612, 613,
                                  614, 616, 617, 618,
                                  620, 621, 622, 623,
                                  625, 626, 627, 628,
                                  629, 631, 632, 633,
                                  634, 636, 637, 638,
                                  639, 641, 642, 643,
                                  644, 646, 647, 648,
                                  649, 651, 652, 653,
                                  654, 656, 657, 658,
                                  659, 660, 662, 663,
                                  664, 665, 667, 668,
                                  669, 670, 671, 673,
                                  674, 675, 676, 678,
                                  679, 680, 682, 683,
                                  684, 686, 687, 688,
                                  689, 691, 692, 693,
                                  694, 697, 698, 699,
                                  702, 703, 704, 707,
                                  708, 709, 710, 712,
                                  713, 714, 717, 718,
                                  719, 720, 721, 724,
                                  725, 726, 728, 729,
                                  730, 734, 735, 736,
                                  738, 739, 740, 742,
                                  743, 744, 747, 748,
                                  749, 751, 752, 753,
                                  755, 756, 757, 759,
                                  760, 761, 763, 764,
                                  765, 767, 768, 769,
                                  771, 772, 773, 775,
                                  776, 777, 779, 780,
                                  781, 782, 784, 785,
                                  786, 788, 789, 790,
                                  791, 793, 794, 795,
                                  797, 798, 799, 800,
                                  802, 803, 804, 807,
                                  813, 814, 815, 816,
                                  818, 822, 823, 824,
                                  825, 830, 831, 832,
                                  834, 835, 836, 837,
                                  839, 840, 841, 842,
                                  844, 845, 846, 848,
                                  849, 850, 852, 853,
                                  855, 856, 858, 859,
                                  860, 862, 863, 864,
                                  866, 867, 868, 870,
                                  871, 872, 874, 875,
                                  876, 877, 879, 880,
                                  881, 883, 884, 886,
                                  888, 889, 891, 892,
                                  893, 895, 899, 900,
                                  902, 903, 905, 906,
                                  908, 909, 911, 912,
                                  914, 915, 917, 918,
                                  920, 921, 923, 925,
                                  927, 929, 931, 932,
                                  934, 936, 938, 940,
                                  942, 944, 946, 948,
                                  950, 952, 953, 955,
                                  956, 958, 959, 961,
                                  962, 963, 965, 966,
                                  968, 969, 971, 972,
                                  974, 975, 977, 978,
                                  979, 981, 982, 983,
                                  987, 988, 991, 992,
                                  994, 995, 996, 998,
                                  1000, 1001, 1002, 1003,
                                  1005, 1007, 1008, 1009,
                                  1011, 1013, 1014, 1016,
                                  1017, 1019, 1020, 1022,
                                  1023, 1024, 1025, 1028,
                                  1029, 1032, 1033, 1035,
                                  1036, 1038, 1040, 1041,
                                  1043, 1045, 1046, 1049,
                                  1050, 1052, 1053, 1055,
                                  1056, 1059, 1060, 1063,
                                  1064, 1067, 1068, 1070,
                                  1071, 1073, 1074, 1076,
                                  1077, 1079, 1080, 1082,
                                  1083, 1087, 1088, 1090,
                                  295, 296, 338, 1551,
                                  1552, 1554, 1556, 1559,
                                  1561, 1563, 1565, 1567,
                                  1568, 1570, 1572, 1574,
                                  1576, 1578, 1580, 1581,
                                  1583, 1585, 1587, 1589,
                                  1591, 1593, 1595, 1597,
                                  1599, 1601, 1603, 1605,
                                  1607, 1609, 1611, 1613,
                                  1614, 1617, 1618, 1621,
                                  1622, 1625, 1626, 1629,
                                  1630, 1634, 1638, 1639,
                                  1642, 1643, 1645, 1646,
                                  1651, 1652, 1657, 1658,
                                  1662, 1664, 1666, 1669,
                                  1672, 1676, 1674, 1677,
                                  1680, 1681, 1684, 1685,
                                  1689, 1690, 1694, 1698,
                                  1704, 1706, 1709, 1712, 1633 )
               AND DataSourceActivityLog.Id = (SELECT DataSourceActivityLog.Id
                                               FROM   DataSourceActivityLog
                                               WHERE  DataSourceActivityLog.DataSourceId = DataSource.Id
                                                      AND ( DataSourceActivityLog.Description = 'data_entry_ready' )
                                               ORDER  BY TIMESTAMP DESC
                                               LIMIT  1)
               AND ( DataSource.Status = '103' )
               AND Workflow.Id = 14
               AND DataSourceActivityLog.`DataSourceId` = DataSource.`Id`
               AND DataSource.`WorkflowId` = Workflow.`Id`
               AND DataSource.IsDeleted = 0) AS WrappedData
ORDER  BY WrappedData.`Timestamp` ASC
LIMIT  0, 1 

2 个答案:

答案 0 :(得分:5)

首先,这是一个很大的子查询似乎很奇怪。你为什么不能这样做:

SELECT DataSource.Id,
               DataSourceActivityLog.Description,
               DataSourceActivityLog.UserId,
               DataSource.Status    AS StatusCode,
               ( CASE
                   WHEN User.Name IS NULL THEN 'System'
                   ELSE User.Name
                 END )              AS `Username`,
               ReadyLog.`Timestamp` AS `Received`,
               DataSourceActivityLog.`Timestamp`
        FROM   DataSource
               LEFT JOIN DataSourceActivityLog AS ReadyLog
                 ON ( ( ReadyLog.DataSourceId = DataSource.Id
                        AND ReadyLog.Description = 'ready' )
                       OR ( ReadyLog.DataSourceId = DataSource.RootId
                            AND ReadyLog.Description = 'ready' ) ),
               DataSourceActivityLog
               LEFT JOIN USER
                 ON USER.Id = DataSourceActivityLog.UserId,
               Workflow
        WHERE  DataSource.Id IN (... )
               AND DataSourceActivityLog.Id = (SELECT DataSourceActivityLog.Id
                                               FROM   DataSourceActivityLog
                                               WHERE  DataSourceActivityLog.DataSourceId = DataSource.Id
                                                      AND ( DataSourceActivityLog.Description = 'data_entry_ready' )
                                               ORDER  BY TIMESTAMP DESC
                                               LIMIT  1)
               AND ( DataSource.Status = '103' )
               AND Workflow.Id = 14
               AND DataSourceActivityLog.`DataSourceId` = DataSource.`Id`
               AND DataSource.`WorkflowId` = Workflow.`Id`
               AND DataSource.IsDeleted = 0
ORDER  BY DataSourceActivityLog.`Timestamp` ASC
LIMIT  0, 1 

我怀疑,但可能是错误的,导致WrappedData导致ORDER BY效率低下,因为它无法使用任何索引,必须等待整个查询在排序之前完成。

接下来,似乎某些where子句应该像这样进入连接:

SELECT DataSource.Id,
               DataSourceActivityLog.Description,
               DataSourceActivityLog.UserId,
               DataSource.Status    AS StatusCode,
               ( CASE
                   WHEN User.Name IS NULL THEN 'System'
                   ELSE User.Name
                 END )              AS `Username`,
               ReadyLog.`Timestamp` AS `Received`,
               DataSourceActivityLog.`Timestamp`
        FROM   DataSource
               LEFT JOIN DataSourceActivityLog AS ReadyLog
                 ON ( ( ReadyLog.DataSourceId = DataSource.Id
                        AND ReadyLog.Description = 'ready' )
                       OR ( ReadyLog.DataSourceId = DataSource.RootId
                            AND ReadyLog.Description = 'ready' ) ),
               INNER JOIN DataSourceActivityLog  ON DataSourceActivityLog.`DataSourceId` = DataSource.`Id`
                                               AND DataSourceActivityLog.Id = (SELECT DataSourceActivityLog.Id
                                               FROM   DataSourceActivityLog
                                               WHERE  DataSourceActivityLog.DataSourceId = DataSource.Id
                                                      AND ( DataSourceActivityLog.Description = 'data_entry_ready' )
                                               ORDER  BY TIMESTAMP DESC
                                               LIMIT  1)
               LEFT JOIN USER
                 ON USER.Id = DataSourceActivityLog.UserId
               INNER JOIN Workflow ON DataSource.`WorkflowId` = Workflow.`Id`
        WHERE  DataSource.Id IN (... )
               AND ( DataSource.Status = '103' )
               AND Workflow.Id = 14
               AND DataSource.IsDeleted = 0
ORDER  BY DataSourceActivityLog.`Timestamp` ASC
LIMIT  0, 1 

此外,别名DataSourceActivityLog AS ReadyLog看起来好像返回了很多行。这应该是INNER JOIN而不是LEFT JOIN吗?根据你提供的内容很难分辨。

最后,DataSource.Id IN (... )是如此之长,将这些ID放入查找表中可能会让您受益,您可以通过连接引用它们,而不是将它们全部输出到where子句中。

我知道这对EXPLAIN没有帮助,但说实话,我认为在这种情况下你不会给你太多的帮助。

答案 1 :(得分:0)

我会尝试以下方法,首先将IN子句的Id放在临时表(TempIds)中;如果您可以确定表Id=14中存在Workflow的记录,那么您可以删除INNER JOINWorkflow表,并保留DataSource.WorkflowId = 14的简单条件在WHERE子句中;然后更改连接的顺序,以便首先评估INNER JOIN,然后LEFT JOIN;简化第一个LEFT JOIN表达式并将不变条件ReadyLog.Description = 'ready'移出OR

SELECT DataSource.Id,
    DataSourceActivityLog.Description,
    DataSourceActivityLog.UserId,
    DataSource.Status    AS StatusCode,
    ( CASE
        WHEN User.Name IS NULL THEN 'System'
        ELSE User.Name
    END )              AS `Username`,
    ReadyLog.`Timestamp` AS `Received`,
    DataSourceActivityLog.`Timestamp`
FROM
    TempIds INNER JOIN
    DataSource ON TempIds.Id = DataSource.Id INNER JOIN
    DataSourceActivityLog ON DataSourceActivityLog.DataSourceId = DataSource.Id 
        AND DataSourceActivityLog.Id = (
            SELECT DataSourceActivityLog.Id
            FROM   DataSourceActivityLog
            WHERE  DataSourceActivityLog.Description = 'data_entry_ready'
                AND DataSourceActivityLog.DataSourceId = DataSource.Id
            ORDER  BY TIMESTAMP DESC
            LIMIT  1) LEFT JOIN
    DataSourceActivityLog AS ReadyLog ON ReadyLog.Description = 'ready'
        AND (ReadyLog.DataSourceId = DataSource.Id
             OR ReadyLog.DataSourceId = DataSource.RootId) LEFT JOIN
    USER ON USER.Id = DataSourceActivityLog.UserId
WHERE
    DataSource.Status = '103'
    AND DataSource.WorkflowId = 14
    AND DataSource.IsDeleted = 0
ORDER  BY DataSourceActivityLog.`Timestamp` ASC
LIMIT  0, 1;

最后,您应该考虑将以下索引添加到DataSourceActivityLog表:

(Description ASC, DataSourceId ASC)