加快MYSQL查询:IN运算符中的大量值

时间:2020-01-09 06:22:15

标签: mysql performance

我有一张桌子,上面有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                |                |
+---------------------+---------------------+------+-----+---------------------+----------------+

我还在ownerIdupdatedAt上创建索引,甚至在名为(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 | +----+-------------+------------+--------+---------------------------------------+-----------+---------+--------------------------+----------+----------+--------------------------------------------------+ ,但这还是行不通的。

1 个答案:

答案 0 :(得分:0)

正如您所说,您正在使用支持降序索引的MYSQL 8 然后尝试使用此索引检查性能。

CREATE INDEX TABLE_NAME
ON Persons (updatedAt DESC,ownerId ASC );

Source

相关问题