【发布时间】:2018-04-09 06:17:00
【问题描述】:
我有一个简单的表来存储流量数据:
CREATE TABLE `domain_traffic` (
`dtraff_id` int(10) UNSIGNED NOT NULL,
`domain_id` int(10) UNSIGNED NOT NULL,
`dtraff_time` bigint(20) UNSIGNED NOT NULL,
`dtraff_web` bigint(20) UNSIGNED DEFAULT '0',
`dtraff_ftp` bigint(20) UNSIGNED DEFAULT '0',
`dtraff_mail` bigint(20) UNSIGNED DEFAULT '0',
`dtraff_pop` bigint(20) UNSIGNED DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `domain_traffic`
ADD PRIMARY KEY (`dtraff_id`),
ADD KEY `domain_id` (`domain_id`);
ALTER TABLE `domain_traffic`
MODIFY `dtraff_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
通过强制使用 domain_id 索引(MySQL 默认执行的操作)运行以下查询大约需要 12 秒:
SELECT SQL_NO_CACHE
SUM(dtraff_web) as web,
SUM(dtraff_ftp) as ftp,
SUM(dtraff_mail) as mail,
SUM(dtraff_pop) as pop
FROM domain_traffic FORCE INDEX (domain_id)
WHERE domain_id = 150
但是
上面要求 MySQL 忽略 domain_id 索引的相同查询只需要大约 2 秒(无论如何这仍然很糟糕):
SELECT SQL_NO_CACHE
SUM(dtraff_web) as web,
SUM(dtraff_ftp) as ftp,
SUM(dtraff_mail) as mail,
SUM(dtraff_pop) as pop
FROM domain_traffic IGNORE INDEX (domain_id)
WHERE domain_id = 150
我真的很惊讶这样的结果,我真的很想知道为什么会这样......
EXPLAIN 两个查询:
使用 domain_id 索引:
+------+-------------+----------------+------+---------------+-----------+---------+-------+---------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------------+------+---------------+-----------+---------+-------+---------+-------+
| 1 | SIMPLE | domain_traffic | ref | domain_id | domain_id | 4 | const | 2069312 | |
+------+-------------+----------------+------+---------------+-----------+---------+-------+---------+-------+
忽略 domain_id 索引
+------+-------------+----------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | domain_traffic | ALL | NULL | NULL | NULL | NULL | 4138625 | Using where |
+------+-------------+----------------+------+---------------+------+---------+------+---------+-------------
记录在案:
- MySQL 供应商:MariaDB 10.1
- ID 为 150 的域的行数:4156659
有什么解释和建议吗?
谢谢。
没有优化提示的结果(遵循@Bill Karwin 的回答):
MariaDB [imscp]> EXPLAIN
SELECT SQL_NO_CACHE
SUM(dtraff_web) as web, SUM(dtraff_ftp) as ftp,
SUM(dtraff_mail) as mail, SUM(dtraff_pop) as pop
FROM domain_traffic WHERE domain_id = 150;
+------+-------------+----------------+------+---------------+-----------+---------+-------+---------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------------+------+---------------+-----------+---------+-------+---------+-------+
| 1 | SIMPLE | domain_traffic | ref | domain_id | domain_id | 4 | const | 2069312 | |
+------+-------------+----------------+------+---------------+-----------+---------+-------+---------+-------+
1 row in set (0.00 sec)
MariaDB [imscp]> SELECT SQL_NO_CACHE
SUM(dtraff_web) as web, SUM(dtraff_ftp) as ftp,
SUM(dtraff_mail) as mail, SUM(dtraff_pop) as pop
FROM domain_traffic WHERE domain_id = 150;
+--------------+--------------+--------------+--------------+
| web | ftp | mail | pop |
+--------------+--------------+--------------+--------------+
| 105989792928 | 106045788277 | 105954990092 | 105942540350 |
+--------------+--------------+--------------+--------------+
1 row in set (8.53 sec)
【问题讨论】:
-
这个问题与stackoverflow.com/questions/46757781/mysql-not-using-index/… 非常相似,但并不完全重复
-
这 4 个数字几乎不可能完全相同。建议您检查其有效性。 (mail 和 pop 是有意义的,但不是其他的。)
-
@RickJames 这些非常相似,因为我使用 rand 创建了用于测试目的的行。
-
@Nuxwin - 呵呵,当然。