您好 我在几乎相同的SQL查询上有一个奇怪的执行时间行为
Q 1:
SELECT `t1`.`id`, `t1`.`key`, `t1`.`module`, `t2`.`value`
FROM `translates` AS `t1`
LEFT JOIN `translates_i18n` AS `t2` ON (`t2`.`id` = `t1`.`id` AND `t2`.`culture` = 'en')
WHERE `t1`.`module` IN ('GLOBAL','AJAX','FORMS', .... about 15 items) LIMIT 9000;
0.10秒
Q2:
SELECT `t1`.`id`, `t1`.`key`, `t2`.`value`
FROM `translates` AS `t1`
LEFT JOIN `translates_i18n` AS `t2` ON (`t2`.`id` = `t1`.`id` AND `t2`.`culture` = 'en')
WHERE `t1`.`module` IN ('GLOBAL','AJAX','FORMS', .... about 15 items) LIMIT 9000;
0.000 ...秒
表定义:
CREATE TABLE IF NOT EXISTS `translates` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`key` varchar(255) NOT NULL,
`module` varchar(255) NOT NULL,
`system` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `key` (`key`,`module`),
KEY `module` (`module`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
CREATE TABLE IF NOT EXISTS `translates_i18n` (
`id` int(11) unsigned NOT NULL,
`culture` varchar(2) NOT NULL,
`value` text NOT NULL,
PRIMARY KEY (`id`,`culture`),
KEY `culture` (`culture`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `translates_i18n`
ADD CONSTRAINT `translates_i18n_ibfk_1` FOREIGN KEY (`id`) REFERENCES `translates` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
q1&之间的区别q2位于t1
。module
列中,也位于where语句中
我只是看不出问题出在哪里,拜托,任何人都会把我弄死。
更新
Q 1:
mysql> EXPLAIN SELECT SQL_NO_CACHE `t1`.`id` , `t1`.`key` , `t1`.`module` , `t2`.`value`
-> FROM `translates` AS `t1`
-> LEFT JOIN `translates_i18n` AS `t2` ON ( `t2`.`id` = `t1`.`id`
-> AND `t2`.`culture` = 'en' )
-> WHERE `t1`.`module`
-> IN (
-> 'GLOBAL', 'AJAX', 'FORMS', 'ROOTMENU', 'LANGSWITCHER', 'AUTHORIZATION', 'MENU', 'MINIFY', 'SIMPLESHOP'
-> )
-> LIMIT 100500
-> ;
+----+-------------+-------+--------+-----------------+---------+---------+---------------------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-----------------+---------+---------+---------------------+------+--------------------------+
| 1 | SIMPLE | t1 | index | module | key | 1534 | NULL | 627 | Using where; Using index |
| 1 | SIMPLE | t2 | eq_ref | PRIMARY,culture | PRIMARY | 12 | theloom.t1.id,const | 1 | |
+----+-------------+-------+--------+-----------------+---------+---------+---------------------+------+--------------------------+
2 rows in set (0.00 sec)
Q2:
mysql> EXPLAIN SELECT SQL_NO_CACHE `t1`.`id` , `t1`.`key` , `t2`.`value`
-> FROM `translates` AS `t1`
-> LEFT JOIN `translates_i18n` AS `t2` ON ( `t2`.`id` = `t1`.`id`
-> AND `t2`.`culture` = 'en' )
-> WHERE `t1`.`module`
-> IN (
-> 'GLOBAL', 'AJAX', 'FORMS', 'ROOTMENU', 'LANGSWITCHER', 'AUTHORIZATION', 'MENU', 'MINIFY', 'SIMPLESHOP'
-> )
-> LIMIT 100500;
+----+-------------+-------+--------+-----------------+---------+---------+---------------------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-----------------+---------+---------+---------------------+------+--------------------------+
| 1 | SIMPLE | t1 | index | module | key | 1534 | NULL | 627 | Using where; Using index |
| 1 | SIMPLE | t2 | eq_ref | PRIMARY,culture | PRIMARY | 12 | theloom.t1.id,const | 1 | |
+----+-------------+-------+--------+-----------------+---------+---------+---------------------+------+--------------------------+
2 rows in set (0.00 sec)
答案 0 :(得分:3)
考虑到这一点,我认为原因就像是the INNODB Buffer Pool。第一个查询以干净缓冲区开始,因此在它处理查询之前,它需要将索引读入内存。然后当你运行第二个查询时,它已经在内存中,所以运行得更快。
尝试在每个查询之间添加FLUSH TALBES
命令。
您也可以尝试使用Benchmark()
功能对此进行测试。
可能导致差异的另一件事是要传输的数据的大小。我看到附加列被声明为VARCHAR(255)
。是否该列有大量数据,9000行确实会显着增加网络开销......
至少要研究一些事情......
答案 1 :(得分:0)
基于对其他答案的讨论以及无缓存的添加,它不太可能与任何缓存有任何关系。计划完全相同,所以没有任何方向。
因此,最可能的原因是检索和存储varchar(255)列。
尝试这3个新查询,看看你得到了什么:
仅计算长度,仍然稍微处理模块列
SELECT `t1`.`id`, `t1`.`key`, Length(`t1`.`module`), `t2`.`value`
FROM `translates` AS `t1`
LEFT JOIN `translates_i18n` AS `t2` ON (`t2`.`id` = `t1`.`id` AND `t2`.`culture` = 'en')
WHERE `t1`.`module` IN ('GLOBAL','AJAX','FORMS', .... about 15 items) LIMIT 9000;
仅测试掩码是否为空
SELECT `t1`.`id`, `t1`.`key`, case when `t1`.`module` is null then 1 else 0 end, `t2`.`value`
FROM `translates` AS `t1`
LEFT JOIN `translates_i18n` AS `t2` ON (`t2`.`id` = `t1`.`id` AND `t2`.`culture` = 'en')
WHERE `t1`.`module` IN ('GLOBAL','AJAX','FORMS', .... about 15 items) LIMIT 9000;
收集所涉及的varchars的总长度
SELECT Length(GROUP_CONCAT(module))
FROM
(
SELECT `t1`.`id`, `t1`.`key`, `t1`.`module`, `t2`.`value`
FROM `translates` AS `t1`
LEFT JOIN `translates_i18n` AS `t2` ON (`t2`.`id` = `t1`.`id` AND `t2`.`culture` = 'en')
WHERE `t1`.`module` IN ('GLOBAL','AJAX','FORMS', .... about 15 items) LIMIT 9000
) X