1

我正在尝试优化以下查询但没有成功。知道在哪里可以索引它以防止临时表和文件排序吗?

EXPLAIN SELECT SQL_NO_CACHE `groups`.*
FROM `groups`
INNER JOIN `memberships` ON `groups`.id = `memberships`.group_id
WHERE ((`memberships`.user_id = 1) 
  AND (`memberships`.`status_code` = 1 AND `memberships`.`manager` = 0))
ORDER BY groups.created_at DESC LIMIT 5;`

+----+-------------+-------------+--------+--------------------------+---------+---------+---------------------------------------------+------+----------------------------------------------+
| id | select_type | table       | type   | possible_keys            | key     | key_len | ref                                         | rows | Extra                                        |
+----+-------------+-------------+--------+--------------------------+---------+---------+---------------------------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | memberships | ref    | grp_usr,grp,usr,grp_mngr | usr     | 5       | const                                       |    5 | Using where; Using temporary; Using filesort | 
|  1 | SIMPLE      | groups      | eq_ref | PRIMARY                  | PRIMARY | 4       | sportspool_development.memberships.group_id |    1 |                                              | 
+----+-------------+-------------+--------+--------------------------+---------+---------+---------------------------------------------+------+----------------------------------------------+
2 rows in set (0.00 sec)


    +--------+------------+-----------------------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+
| Table  | Non_unique | Key_name                          | Seq_in_index | Column_name     | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------+------------+-----------------------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+
| groups |          0 | PRIMARY                           |            1 | id              | A         |           6 |     NULL | NULL   |      | BTREE      |         | 
| groups |          1 | index_groups_on_name              |            1 | name            | A         |           6 |     NULL | NULL   | YES  | BTREE      |         | 
| groups |          1 | index_groups_on_privacy_setting   |            1 | privacy_setting | A         |           6 |     NULL | NULL   | YES  | BTREE      |         | 
| groups |          1 | index_groups_on_created_at        |            1 | created_at      | A         |           6 |     NULL | NULL   | YES  | BTREE      |         | 
| groups |          1 | index_groups_on_id_and_created_at |            1 | id              | A         |           6 |     NULL | NULL   |      | BTREE      |         | 
| groups |          1 | index_groups_on_id_and_created_at |            2 | created_at      | A         |           6 |     NULL | NULL   | YES  | BTREE      |         | 
+--------+------------+-----------------------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+


     +-------------+------------+----------------------------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table       | Non_unique | Key_name                                                 | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------------+------------+----------------------------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| memberships |          0 | PRIMARY                                                  |            1 | id          | A         |           2 |     NULL | NULL   |      | BTREE      |         | 
| memberships |          0 | grp_usr                                                  |            1 | group_id    | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| memberships |          0 | grp_usr                                                  |            2 | user_id     | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| memberships |          1 | grp                                                      |            1 | group_id    | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| memberships |          1 | usr                                                      |            1 | user_id     | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| memberships |          1 | grp_mngr                                                 |            1 | group_id    | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| memberships |          1 | grp_mngr                                                 |            2 | manager     | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| memberships |          1 | complex_index                                            |            1 | group_id    | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| memberships |          1 | complex_index                                            |            2 | user_id     | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| memberships |          1 | complex_index                                            |            3 | status_code | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| memberships |          1 | complex_index                                            |            4 | manager     | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| memberships |          1 | index_memberships_on_user_id_and_status_code_and_manager |            1 | user_id     | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| memberships |          1 | index_memberships_on_user_id_and_status_code_and_manager |            2 | status_code | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| memberships |          1 | index_memberships_on_user_id_and_status_code_and_manager |            3 | manager     | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
+-------------+------------+----------------------------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
4

5 回答 5

0
  • memberships列索引user_id(如果是 PK 应该已经有一个)
  • memberships列上的索引status_codemanager (它们都在同一个索引上)
  • groups列上的索引created_at(如果可能,使用默认 DESC,我不知道您是否可以在 mySql 中)

这就是我在 MS SQL Server 中要做的,但我想同样的优化也可以在 mySql 中使用。

于 2009-11-10T22:08:04.377 回答
0

您在加入的字段、where 子句中的字段和您订购的 created_at 字段上是否拥有所有“明显”的单列索引?

于 2009-11-10T22:08:10.603 回答
0

问题是你需要一个关于组的索引来消除文件排序,但你所有的 where 条件都是关于成员资格的。

尝试在 (id, created_at) 上的组上添加索引。

如果这不起作用,请尝试使用子查询来欺骗优化器(将上述索引保留在组上):

SELECT SQL_NO_CACHE `groups`.*
    FROM `groups`
    INNER JOIN (select group_id from `memberships`
       WHERE 
           `memberships`.user_id = 1
           AND `memberships`.`status_code` = 1
           AND `memberships`.`manager` = 0
    ) m on m.group_id=`groups`.id
    ORDER BY groups.created_at DESC LIMIT 5;

至少在memberships.user_id 上应该有一个索引,但您也可以从(user_id、status、manager)之类的索引中获得一些好处。我假设 status 和 manager 是没有大范围可能值的标志,所以只要 user_id 上有一个索引,它就不是那么重要。

于 2009-11-10T22:14:46.877 回答
0

一个(user_id, status_code, manager)(以任何顺序)索引memberships会有所帮助。

避免排序会很困难,因为您必须在组表中开始连接,这意味着您不能使用引用该memberships表的所有(可能非常有选择性的)where 子句,直到为时已晚。

于 2009-11-10T22:48:21.223 回答
0

感谢您发布有关您正在使用的索引的详细信息。

我已经对此进行了测试,并尝试省略一些索引。大多数索引是memberships.complex_index作为一个覆盖索引。这允许查询通过仅读取索引来实现其结果;它根本不需要读取数据行memberships

上的任何索引groups都没有任何区别。无论如何,它似乎都使用文件排序。MySQL 中的 Filesort 仅仅意味着它正在执行表扫描,在某些情况下,这可能比使用索引更便宜。例如,如果groups无论如何都需要读取每一行以产生查询结果,那么为什么还要通过使用索引来进行不必要的双重查找呢?优化器可以感知这些情况并且可以适当地拒绝使用索引。

因此,除了主键索引和 之外complex_index,我会删除所有其他索引,因为它们没有帮助,只会增加维护这些表的成本。

于 2009-11-11T21:35:39.420 回答