MySQL 选择查询非常慢

Posted

技术标签:

【中文标题】MySQL 选择查询非常慢【英文标题】:MySQL select query is terribly slow 【发布时间】:2019-11-08 12:48:14 【问题描述】:

我有一张包含 2 196 998 条记录的表格:

CREATE TABLE price (
    dt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    marketId INT,
    buy DOUBLE,
    sell DOUBLE,
    PRIMARY KEY (dt, marketId),
    FOREIGN KEY fk_price_market(marketId) REFERENCES market(id) ON UPDATE CASCADE ON DELETE CASCADE
)  ENGINE=INNODB;

查询

select max(buy) from price;

需要 1.92 秒,这是一个合理的时间,如果我在“购买”列上创建索引,则需要 0.00 秒:

CREATE INDEX idx_price_buy ON price (buy);

还有查询

select count(*) from price where marketId=309;

耗时 0.05 秒并返回 160 570。

但是查询

select max(buy) from price where marketId=309;

即使我创建了两个 idice,也需要 15.49 秒(这非常大):

CREATE INDEX idx_price_market ON price (marketId);
CREATE INDEX idx_price_buy ON price (buy);

(我不确定,但可能索引idx_price_market 已经存在,因为在外键约束中需要marketId 列)

1) 有没有办法优化它?

2) 如果不是,那么其他数据库呢?他们的表现更好吗?

EDIT1:

创建复合索引后

CREATE INDEX idx_price_market_buy ON price (marketId, buy);

查询耗时 0.00 秒。

desc select max(buy) from price where marketId=309;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                        |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
|  1 | SIMPLE      | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | Select tables optimized away |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
1 row in set, 1 warning (0.01 sec)

【问题讨论】:

你可以测试一下,mysql是否使用desc的索引。所以使用desc select max(buy) from price where marketId=309;如果mysql使用索引,它会写在那个结果的'Extra'列中 MySQL 一次只能使用一个想法。如果您引用多个列,那么您可能需要考虑使用复合索引。 看起来很完美:Link 以上链接中的相关信息:“查询仅包含使用索引解析的聚合函数 (MIN()、MAX()),或 MyISAM 的 COUNT(*),以及没有 GROUP BY 子句。优化器确定应该只返回一行。" 这是关于构建最佳索引的课程:mysql.rjweb.org/doc.php/index_cookbook_mysql 【参考方案1】:
select max(buy) from price where marketId=309;

在每列上创建单独的索引可能不允许 MySQL 优化查询。

对于此查询,您需要(marketId, buy) 上的复合索引

create index idx_price_market_buy ON price (marketId, buy);

索引中列的顺序很重要:首先查询过滤器marketId(因此您希望此列在复合索引中的第一个位置),然后它计算最大值buy .

【讨论】:

“在每列上创建单独的索引可能不允许 MySQL 优化查询。” 事实上策略 “index shotgun” (@987654321 @) 在某些时候真的会“反击” ...

以上是关于MySQL 选择查询非常慢的主要内容,如果未能解决你的问题,请参考以下文章

如何优化这个非常慢的 MySQL 查询?

MySql分区表 - 使用PK的日期范围之间选择与日期IN(...)子句相比非常慢

带有多个选择语句的 MySQL 右外连接非常慢

MySQL 查询慢,按限制按顺序分组

mysql索引的选择

mysql慢查询和php-fpm慢日志