2011-01-25 63 views
0

你好 我有一個奇怪的執行時間上的行爲基本相同的SQL查詢奇怪的MySQL查詢執行時間的行爲

Q1:

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 ...秒

表定義:Q1 & Q2之間

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; 

區別是在t1module列,這也是在聲明中

我只是不能看到問題出在哪裏,請,任何人POIT我

更新

Q1:

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) 
+2

爲兩個查詢顯示'EXPLAIN'。 – zerkms

+0

看到更新後的帖子 – VoSi

回答

3

看看這個,我認爲原因是由於the INNODB Buffer Pool。第一個查詢從一個乾淨的緩衝區開始,因此在它可以處理查詢之前,它需要將索引讀入內存。然後當你運行第二個查詢時,它已經在內存中,所以它運行得更快。

嘗試在每個查詢之間添加一條FLUSH TALBES命令。

您也可以嘗試使用Benchmark()函數來測試它。

可能導致差異的另一件事是要傳輸的數據的大小。我看到額外的列被宣佈爲VARCHAR(255)。它是也許,列有大量的數據,和9000行確實增加網絡開銷顯著...

有些事情要至少調查...

+0

這些表是在innodb,而不是myisam,所以密鑰緩存不是問題 我看不到任何理由來刷新表,這個查詢是獨立的,我需要第一個查詢形式我的系統,但由於某種原因它慢,所以我調查了爲什麼它很慢,發現它很慢,當我選擇一列在哪裏 – VoSi

+0

+1最有可能只是時間來填充一些內存與9000 varchar(255)值。計劃是完全一樣的,所以它必須與數據量相關 – RichardTheKiwi

+0

@VoSi:好點,從KeyCache編輯到緩衝池...試一試:每次運行查詢幾百次,並平均時間。然後它會告訴你它是否是緩衝池問題。還要檢查wirehark之​​類的東西,看看有多少數據實際傳輸(這將告訴你,如果差異是在網絡堆棧中)... – ircmaxell

0

基於對其他的討論答案,以及增加no-cache,它不可能與任何緩存有關。這些計劃也完全一樣,所以沒有朝這個方向發展。

因此,最可能的原因是檢索和存儲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; 

收集涉及的變種的總長度

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 
+0

q1:時間0.0004毫秒最小長度是4最大值是13 – VoSi

+0

q2:一切都是0,沒有空模塊字段 – VoSi

+0

我認爲它是增強事實上,你對模塊的處理越多,需要的時間就越長。我忘記了長度計數是非常有效的,因爲它只查看varchar的前幾個字節,因此實際上檢索數據會顯得不重要,但0.0004ms已經是一個變化。 – RichardTheKiwi