当EXPLAIN看起来那么好时,为什么这个查询会检查这么多行?

时间:2011-12-20 17:24:16

标签: mysql performance

我有以下查询:

SELECT  mdg.id AS mdg_id, vdk.id AS vdisk_id, vdk.name AS vdisk_name, vdk.objKey AS vdisk_key,
        vdc.type AS copy_type, vde.copy_id AS copy_id, mdk.id AS mdisk_id, vde.number_extents AS extent_count,
        IFNULL(ter.name,'generic_hdd') AS mdisk_tier, mdg.snapKey, vde.objKey AS row_key
    FROM       mdisk_grp   AS mdg
    INNER JOIN vdiskcopy   AS vdc ON mdg.snapKey = vdc.snapKey AND mdg.id = vdc.mdisk_grp_id
    INNER JOIN vdisk       AS vdk ON vdc.owner = vdk.objKey
    INNER JOIN vdiskextent AS vde ON vdk.snapKey=vde.snapKey AND vdk.id = vde.vdisk_id AND vdc.copy_id = vde.copy_id
    INNER JOIN mdisk       AS mdk ON vde.id = mdk.id AND vde.snapKey = mdk.snapKey
    LEFT  JOIN tier_mdisk  AS tmk ON tmk.mdisk_objKey = mdk.objKey
    LEFT  JOIN tier        AS ter ON tmk.tier_objKey = ter.objKey
    WHERE mdg.snapKey= '333';

我经常在慢查询日志中看到它(当然是mdg.snapKey的不同值);例如:

# User@Host: svcControl[svcControl] @ localhost []
# Query_time: 2577  Lock_time: 0  Rows_sent: 11469  Rows_examined: 354942843

考虑到要检查的行数,它运行时间长这一事实并不奇怪。

但是,当我EXPLAIN查询时,我看到了

+----+-------------+-------+--------+---------------------------------------------------------+--------------------+---------+------------------------+------+---------------------+
| id | select_type | table | type   | possible_keys                                           | key                | key_len | ref                    | rows | Extra               |
+----+-------------+-------+--------+---------------------------------------------------------+--------------------+---------+------------------------+------+---------------------+
|  1 | SIMPLE      | tmk   | system | mdisk_objKey_idx                                        | NULL               | NULL    | NULL                   |    0 | const row not found |
|  1 | SIMPLE      | ter   | const  | PRIMARY                                                 | NULL               | NULL    | NULL                   |    1 |                     |
|  1 | SIMPLE      | mdg   | ref    | mdisk_grp_id_idx,snapIdx                                | snapIdx            | 2       | const                  |   11 |                     |
|  1 | SIMPLE      | vdc   | ref    | snapIdx,mdgIdIdx,ownerIdx                               | mdgIdIdx           | 5       | svcObjects.mdg.id      |    1 | Using where         |
|  1 | SIMPLE      | vdk   | eq_ref | PRIMARY,vdisk_id_idx,snapIdx                            | PRIMARY            | 3       | svcObjects.vdc.owner   |    1 |                     |
|  1 | SIMPLE      | mdk   | ref    | mdisk_id_idx,snapKey_idx                                | snapKey_idx        | 2       | svcObjects.vdk.snapKey |   16 |                     |
|  1 | SIMPLE      | vde   | ref    | vdiskextent_id_idx,vdiskextent_vdisk_id_idx,snapKey_idx | vdiskextent_id_idx | 5       | svcObjects.mdk.id      |   23 | Using where         |
+----+-------------+-------+--------+---------------------------------------------------------+--------------------+---------+------------------------+------+---------------------+

将所有这些行相乘得多于4000(忽略列中的0)

出现,忽略了执行计划。

有没有办法运行查询然后获取报告以及实际遵循的执行计划?或者我误解了这个输出?

更新 我注意到我的一些索引的基数是NULL,所以我ANALYZE d所有表。最新的EXPLAIN报告:

+----+-------------+-------+--------+---------------------------------------------------------+--------------------------+---------+----------------------+------+---------------------+
| id | select_type | table | type   | possible_keys                                           | key                      | key_len | ref                  | rows | Extra               |
+----+-------------+-------+--------+---------------------------------------------------------+--------------------------+---------+----------------------+------+---------------------+
|  1 | SIMPLE      | tmk   | system | mdisk_objKey_idx                                        | NULL                     | NULL    | NULL                 |    0 | const row not found |
|  1 | SIMPLE      | ter   | const  | PRIMARY                                                 | NULL                     | NULL    | NULL                 |    1 |                     |
|  1 | SIMPLE      | mdg   | ref    | mdisk_grp_id_idx,snapIdx                                | snapIdx                  | 2       | const                |    8 |                     |
|  1 | SIMPLE      | vdc   | ref    | snapIdx,mdgIdIdx,ownerIdx                               | snapIdx                  | 2       | const                | 1580 | Using where         |
|  1 | SIMPLE      | vdk   | eq_ref | PRIMARY,vdisk_id_idx,snapIdx                            | PRIMARY                  | 3       | svcObjects.vdc.owner |    1 |                     |
|  1 | SIMPLE      | vde   | ref    | vdiskextent_id_idx,vdiskextent_vdisk_id_idx,snapKey_idx | vdiskextent_vdisk_id_idx | 5       | svcObjects.vdk.id    |  300 | Using where         |
|  1 | SIMPLE      | mdk   | ref    | mdisk_id_idx,snapKey_idx                                | mdisk_id_idx             | 5       | svcObjects.vde.id    |   14 | Using where         |
+----+-------------+-------+--------+---------------------------------------------------------+--------------------------+---------+----------------------+------+---------------------+

这个数字最多可以增加到53,088,000,这比慢速查询中检查的354,942,843要好得多。

我想我现在的问题是这个......我所看到的行为是否由我所做的解释...如果索引基数为NULL,那么执行计划将显得过于乐观并且可能导致被检查所需行数的6-7倍?

1 个答案:

答案 0 :(得分:0)