我在优化以下查询以快速运行时遇到问题:
SELECT
co_contracts_cstm.is_master_c,
co_contracts.id id
FROM co_contracts
LEFT JOIN co_contracts_cstm ON co_contracts_cstm.id_c =
co_contracts.id
WHERE co_contracts.deleted = 0 AND co_contracts_cstm.is_master_c = 1
ORDER BY co_contracts.document_name ASC, co_contracts.id DESC LIMIT 0,21
为您提供一些详细信息:co_contracts和co_contracts_cstm表每个包含大约3M个记录,并且它们共享主键,我将加入它们。这些合约中约有1M个的is_master_c属性等于1.
我在(deleted, document_name, id)
上创建了co_contracts
之类的索引,这使得查询运行得非常快(大约4s),但只有 IF 我删除{{1} } WHERE条件。有了它,它运行了一分钟,这太多了。
我需要通过多个列快速订购此表连接,is_master_c
只是一个示例。无论我在document_name
表上尝试什么索引,都没有帮助,查询仍然运行超过一分钟。
我认为问题是,SQL可能只对全部百万条记录进行排序,以返回20条结果。我想一个解决办法就是只有一个表(我不太清楚为什么有两个表),但这是我无法做到的事情 - 它会与控制数据库的管理工具发生冲突。以类似的方式,我有点无法重新设计整个数据库。
如果我向WHERE条件添加更多约束,那么查询会变得更快 - 我认为主要问题是,通过过滤器我丢失了一个索引来进行排序。
编辑:添加EXPLAIN
co_contracts_cstm
为了让您不必担心filesort,即使在没有+----+-------------+-------------------+--------+-----------------------------------------------------+---------------------+---------+--------------------------+---------+------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------------+--------+-----------------------------------------------------+---------------------+---------+--------------------------+---------+------------------------------------------+
| 1 | SIMPLE | co_contracts | ref | PRIMARY,idx_document_name_s | idx_document_name_s | 2 | const | 1251039 | Using where; Using index; Using filesort |
| 1 | SIMPLE | co_contracts_cstm | eq_ref | PRIMARY,idx_master_c | PRIMARY | 108 | sugarcrm.co_contracts.id | 1 | Using where |
+----+-------------+-------------------+--------+-----------------------------------------------------+---------------------+---------+--------------------------+---------+------------------------------------------+
WHERE条件(快速)的查询中,也会在EXPLAIN中声明它。
co_contracts上的相关索引:
is_master_c
co_contracts_cstm上的相关索引要完整:
+--------------+------------+-------------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------------+------------+-------------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| co_contracts | 0 | PRIMARY | 1 | id | A | 2502079 | NULL | NULL | | BTREE | | |
| co_contracts | 1 | idx_document_name_s | 1 | deleted | A | 2 | NULL | NULL | YES | BTREE | | |
| co_contracts | 1 | idx_document_name_s | 2 | document_name | A | 32494 | NULL | NULL | YES | BTREE | | |
| co_contracts | 1 | idx_document_name_s | 3 | id | A | 2502079 | NULL | NULL | | BTREE | | |
+--------------+------------+-------------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
(强制idx_master_c INDEX不起作用,如果它按顺序+-------------------+------------+-----------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------------------+------------+-----------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| co_contracts_cstm | 0 | PRIMARY | 1 | id_c | A | 2502364 | NULL | NULL | | BTREE | | |
| co_contracts_cstm | 1 | idx_master_c | 1 | id_c | A | 2502364 | NULL | NULL | | BTREE | | |
| co_contracts_cstm | 1 | idx_master_c | 2 | is_master_c | A | 2502364 | NULL | NULL | YES | BTREE | | |
+-------------------+------------+-----------------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
或(id_c, is_master)
,则不起作用。