我有一张桌子,上面有14000000个帖子。当我用select语句查询表时(按发布表的datetime字段排序)时,MySQL始终使用文件排序,导致查询时间非常慢(> 3秒)。这是故事表的架构(简化):
+---------------------+---------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+---------------------+------+-----+---------------------+----------------+
| Id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| parentId | bigint(20) unsigned | Yes | MUL | NULL | |
| ownerId | bigint(20) unsigned | NO | MUL | NULL | |
| updatedAt | timestamp(6) | Yes | MUL | CURRENT_TIMESTAMP(6)|DEFAULT_GENERATED|
| createdAt | timestamp(6) | Yes | MUL | CURRENT_TIMESTAMP(6)|DEFAULT_GENERATED|
| message | text | Yes | MUL | NULL | |
| imageUrl | varchar(255) | Yes | | NULL | |
+---------------------+---------------------+------+-----+---------------------+----------------+
我还在ownerId
和updatedAt
上创建索引,甚至在名为(ownerId,updateAt)
的{{1}}上创建复合索引。这是索引表:
ownerId_updatedAt
这是需要3秒钟以上的时间才能执行的查询。id的数量可能会大到大约100。
+------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| TABLE_NAME | 0 | PRIMARY | 1 | Id | A | 13457024 | NULL | NULL | | BTREE | | | YES | NULL |
| TABLE_NAME | 0 | Id_UNIQUE | 1 | Id | A | 13256858 | NULL | NULL | | BTREE | | | YES | NULL |
| TABLE_NAME | 1 | ownerId | 1 | ownerId | A | 899817 | NULL | NULL | | BTREE | | | YES | NULL |
| TABLE_NAME | 1 | updatedAt | 1 | updatedAt | A | 12862943 | NULL | NULL | YES | BTREE | | | YES | NULL |
| TABLE_NAME | 1 | ownerId_updatedAt | 1 | ownerId | A | 838060 | NULL | NULL | | BTREE | | | YES | NULL |
| TABLE_NAME | 1 | ownerId_updatedAt | 2 | updatedAt | A | 13457024 | NULL | NULL | YES | BTREE | | | YES | NULL |
+------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
此查询的explain Extended命令的结果表明,MySQL正在使用文件排序并使用索引条件:
SELECT *
FROM TABLE_NAME
WHERE ownerId IN (id1,id2...,Idn)
AND updatedAt < COALESCE(
( SELECT updatedAt
FROM TABLE_NAME
WHERE storyId = 0),
CURRENT_TIMESTAMP )
AND privacy = 0
ORDER BY updatedAt DESC, ownerId ASC LIMIT 20;
当我部分删除订单时,MySQL停止使用文件排序。如果您对如何优化此查询以使MySQL通过使用索引来排序和选择数据有任何想法,请告诉我。我已经尝试过一些方法,例如在所有按位置/按字段排序的位置上创建组合索引,并根据一些博客文章的建议使用+----+-------------+------------+--------+---------------------------------------+-----------+---------+--------------------------+----------+----------+--------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered |Extra |
+----+-------------+------------+--------+---------------------------------------+-----------+---------+--------------------------+----------+----------+--------------------------------------------------+
| 1 | PRIMARY | TABLE_NAME | range | ownerId,updatedAt,ownerId_updatedAt | ownerId | 8 | NULL | 12792 | 5.00 |Using index condition;Using where; Using filesort |
+----+-------------+------------+--------+---------------------------------------+-----------+---------+--------------------------+----------+----------+--------------------------------------------------+
,但这还是行不通的。
答案 0 :(得分:0)
正如您所说,您正在使用支持降序索引的MYSQL 8 然后尝试使用此索引检查性能。
CREATE INDEX TABLE_NAME
ON Persons (updatedAt DESC,ownerId ASC );