【发布时间】:2017-10-20 10:57:48
【问题描述】:
我正在寻找一些关于 MySQL 表上的索引如何工作的见解,因为我遇到了一些我不理解的问题。
让我们从我正在使用的表开始:
mysql> SHOW CREATE TABLE channeldata\G
*************************** 1. row ***************************
Table: channeldata
Create Table: CREATE TABLE `channeldata` (
`channel_id` smallint(3) unsigned NOT NULL,
`station_id` smallint(5) unsigned NOT NULL,
`time` datetime NOT NULL,
`reading` double NOT NULL DEFAULT '0',
`average` double NOT NULL DEFAULT '0',
`location_lat` double NOT NULL DEFAULT '0',
`location_lon` double NOT NULL DEFAULT '0',
`location_alt` double(8,3) DEFAULT '0.000',
`quality` smallint(3) unsigned DEFAULT '0',
PRIMARY KEY (`channel_id`,`station_id`,`time`),
KEY `composite3` (`station_id`,`channel_id`,`quality`) USING BTREE,
KEY `composite` (`channel_id`,`station_id`,`time`,`quality`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
/*!50100 PARTITION BY RANGE (YEAR(time))
(PARTITION p0 VALUES LESS THAN (2001) ENGINE = MyISAM,
PARTITION p1 VALUES LESS THAN (2002) ENGINE = MyISAM,
PARTITION p2 VALUES LESS THAN (2003) ENGINE = MyISAM,
PARTITION p3 VALUES LESS THAN (2004) ENGINE = MyISAM,
PARTITION p4 VALUES LESS THAN (2005) ENGINE = MyISAM,
PARTITION p5 VALUES LESS THAN (2006) ENGINE = MyISAM,
PARTITION p6 VALUES LESS THAN (2007) ENGINE = MyISAM,
PARTITION p7 VALUES LESS THAN (2008) ENGINE = MyISAM,
PARTITION p8 VALUES LESS THAN (2009) ENGINE = MyISAM,
PARTITION p9 VALUES LESS THAN (2010) ENGINE = MyISAM,
PARTITION p10 VALUES LESS THAN (2011) ENGINE = MyISAM,
PARTITION p11 VALUES LESS THAN (2012) ENGINE = MyISAM,
PARTITION p12 VALUES LESS THAN (2013) ENGINE = MyISAM,
PARTITION p13 VALUES LESS THAN (2014) ENGINE = MyISAM,
PARTITION p14 VALUES LESS THAN (2015) ENGINE = MyISAM,
PARTITION p15 VALUES LESS THAN (2016) ENGINE = MyISAM,
PARTITION p16 VALUES LESS THAN (2017) ENGINE = MyISAM,
PARTITION p17 VALUES LESS THAN (2018) ENGINE = MyISAM) */
1 row in set (0.00 sec)
我正在运行查询以选择 2017 年 8 月/9 月/10 月的数据。“读数”在一天中均匀分布,并且始终以 10 分钟为边界(即 10:10:00、10:20: 00、10:30:00 等)从 2017 年 5 月起,每天的“阅读”数量相当一致,为 15.000。 P17 分区总共有超过 300 万个读数。
我需要帮助的查询如下所示:
SELECT
ROUND(`a`.`average`,2) `average`,
UNIX_TIMESTAMP(`a`.`time`) * 1000 time,
`a`.`station_id`
FROM
`argus`.`channeldata` PARTITION (p17) `a`
WHERE
((`a`.`station_id` = '3002' AND a.channel_id = '1') OR (`a`.`station_id` = '3004' AND a.channel_id = '1') OR [...] OR (`a`.`station_id` = '5052' AND a.channel_id = '1')) AND `a`.`time` BETWEEN "2017-08-17 00:00:00" AND "2017-10-13 23:59:59" AND `a`.`quality` IN('1') ORDER BY `a`.`time` ASC;
这是格式化为清楚地显示WHERE 条件的查询。
SELECT
ROUND(`a`.`average`,2) `average`,
UNIX_TIMESTAMP(`a`.`time`) * 1000 time,
`a`.`station_id`
FROM
`argus`.`channeldata` PARTITION (p17) `a`
WHERE
( (`a`.`station_id` = '3002' AND a.channel_id = '1')
OR (`a`.`station_id` = '3004' AND a.channel_id = '1')
OR [...]
OR (`a`.`station_id` = '5052' AND a.channel_id = '1'))
AND `a`.`time` BETWEEN "2017-08-17 00:00:00" AND "2017-10-13 23:59:59"
AND `a`.`quality` IN('1')
ORDER BY `a`.`time` ASC;
为了获得一些指标,我开始从 4 周、5 周等间隔中选择读数。完成这些查询的执行时间大约为 4 到 5 秒,我在间隔中添加的天数越多,时间就会略有增加。但是,突然之间,执行时间出现了跳跃。在“BETWEEN”间隔中仅增加一天,执行时间几乎翻了两番,达到近 20 秒。
我在解释中运行了之前和之后的查询,结果是我不明白的。
间隔为BETWEEN "2017-08-18 00:00:00" AND "2017-10-13 23:59:59" EXPLAIN 看起来像这样:
+----+-------------+-------+-------+------------------------------+---------+---------+------+--------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+------------------------------+---------+---------+------+--------+-----------------------------+
| 1 | SIMPLE | a | range | PRIMARY,composite3,composite | PRIMARY | 12 | NULL | 542026 | Using where; Using filesort |
+----+-------------+-------+-------+------------------------------+---------+---------+------+--------+-----------------------------+
1 row in set (0.00 sec)
将其增加一天到 BETWEEN "2017-08-17 00:00:00" AND "2017-10-13 23:59:59" 看起来像这样:
+----+-------------+-------+------+------------------------------+------+---------+------+---------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+------------------------------+------+---------+------+---------+-----------------------------+
| 1 | SIMPLE | a | ALL | PRIMARY,composite3,composite | NULL | NULL | NULL | 3056618 | Using where; Using filesort |
+----+-------------+-------+------+------------------------------+------+---------+------+---------+-----------------------------+
1 row in set (0.00 sec)
那里发生了什么?为什么它突然不能使用主键/索引,而不是搜索行的子集,它必须搜索整个 300 万个分区。在旁注中,区间的确切位置并不重要。我也可以通过将间隔提前一个月来重现这个问题。
如果有帮助,在执行时间“跳转”之前返回的列是 525644,当我增加 1 天时的数字是 535004。
【问题讨论】:
-
有多少百分比的数据有
quality=1?
标签: mysql indexing query-performance