首页 > 解决方案 > 为什么我的类似查询的处理方式大不相同?

问题描述

我们有一张桌子

mysql> show create table channeldata\G
*************************** 1. 行 ************ ***************
表:channeldata
创建表:CREATE TABLE channeldata(
channel_idsmallint(3) unsigned NOT NULL,
station_id smallint(5) unsigned NOT NULL,
timedatetime NOT NULL,
readingdouble NOT NULL DEFAULT '0 ',
averagedouble NOT NULL DEFAULT '0',
location_latdouble NOT NULL DEFAULT '0',
location_londouble NOT NULL DEFAULT '0',
location_alt double(8,3) DEFAULT '0.000',
qualitysmallint(3) unsigned DEFAULT '0',
PRIMARY KEY ( channel_id, station_id, time),
KEY composite3( station_id, channel_id, quality) 使用 BTREE,
KEY composite( channel_id, station_id,time,quality) 使用 BTREE ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
1 行 in set (0.00 sec)

最近我注意到我们所做的一些选择查询需要很长时间才能完成。奇怪的是,根据 where 子句中列的值,选择完成的速度要么非常快,要么需要很长时间才能阻止对同一个表的更新。我通过解释运行了这些查询:

mysql> 解释从 channeldata 中选择读取 WHERE station_id = 6001
AND channel_id = 1 AND time < '2018-09-20T14:58:00'\G
******************* ********* 1. 行 ***************************
id: 1 select_type: SIMPLE
table: channeldata
partitions: NULL
类型:ref
possible_keys:PRIMARY,composite3,复合
键:PRIMARY
key_len:4
ref:const,const
行:176539
过滤:33.33
额外:使用索引条件 1 行中的集合,1 个警告(0.00 秒)

mysql> 解释 SELECT 从 channeldata 读取 WHERE station_id = 6001 AND channel_id = 4 AND time < '2018-09-20T14:58:00'\G
******************* ********* 1. 行 ***************************
id: 1 select_type: SIMPLE
table: channeldata
partitions: NULL
类型:范围
possible_keys:PRIMARY,composite3,复合
键:PRIMARY
key_len:9
ref:NULL
行:428073
过滤:100.00
额外:使用索引条件 1 行中的集合,1 个警告(0.00 秒)

为什么过滤不同的值(channel_id 是 4 而不是 1)会有所不同?两个结果集的大小相等。为什么在这两种情况下 MySQL 都选择使用 PRIMARY 键,但 keylen 差异很大。

标签: mysqlindexingquery-performance

解决方案


你有一个错误TMySQL 无法识别时间常数;将其更改为空格。

您应该切换到InnoDB

在 MyISAM 中,将加快查询速度:

INDEX(channel_id, station_id,  -- in either order
      time,
      reading)   -- last

那将是“覆盖”,因此比在索引和数据之间来回切换更快。

回到为什么它们不同......我不知道。但是,其中任何一个都可能有助于 MyISAM 表: ANALYZE TABLEOPTIMIZE TABLE.


推荐阅读