花了幾天時間來分析我們的分佈式應用程序在MySQL數據庫中使用的各種查詢。我們的應用程序可能會在客戶端數據庫服務器上存儲數百萬條記錄,並且查詢可能有所不同,因此索引的設計並不總是清晰或容易。如果查詢速度足夠快,查詢中的一小部分額外開銷就可以接受。MySQL查詢w /索引匹配較少WHERE列比索引匹配所有列的速度更快
我已經設法縮小了幾乎所有我們最常見的查詢都適用的複合索引。我可以清除下列索引中的某些列,但我需要運行測試來確保。
然而,我的問題:某個查詢實際運行更快當使用包含在目前的條件較少的列的索引。
表結構與當前的複合索引:
CREATE TABLE IF NOT EXISTS `prism_data` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`epoch` int(10) unsigned NOT NULL,
`action_id` int(10) unsigned NOT NULL,
`player_id` int(10) unsigned NOT NULL,
`world_id` int(10) unsigned NOT NULL,
`x` int(11) NOT NULL,
`y` int(11) NOT NULL,
`z` int(11) NOT NULL,
`block_id` mediumint(5) DEFAULT NULL,
`block_subid` mediumint(5) DEFAULT NULL,
`old_block_id` mediumint(5) DEFAULT NULL,
`old_block_subid` mediumint(5) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `epoch` (`epoch`),
KEY `block` (`block_id`,`action_id`,`player_id`),
KEY `location` (`world_id`,`x`,`z`,`y`,`epoch`,`action_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
我有我一直在測試8次常見的查詢,他們都表現出50萬條記錄的數據庫上令人難以置信的性能提升。但是,一個查詢不會。
以下查詢中(9.77秒)返回11088行並使用location
索引
SELECT SQL_NO_CACHE id,
epoch,
action,
player,
world_id,
x,
y,
z
FROM prism_data
INNER JOIN prism_players p ON p.player_id = prism_data.player_id
INNER JOIN prism_actions a ON a.action_id = prism_data.action_id
WHERE world_id =
(SELECT w.world_id
FROM prism_worlds w
WHERE w.world = 'world')
AND (a.action = 'world-edit')
AND (prism_data.x BETWEEN -7220 AND -7020)
AND (prism_data.y BETWEEN -22 AND 178)
AND (prism_data.z BETWEEN -9002 AND -8802)
AND prism_data.epoch >= 1392220467;
+----+-------------+------------+--------+----------------+----------+---------+--------------------------------+--------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+----------------+----------+---------+--------------------------------+--------+------------------------------------+
| 1 | PRIMARY | a | ref | PRIMARY,action | action | 77 | const | 1 | Using where; Using index |
| 1 | PRIMARY | prism_data | ref | epoch,location | location | 4 | const | 660432 | Using index condition; Using where |
| 1 | PRIMARY | p | eq_ref | PRIMARY | PRIMARY | 4 | minecraft.prism_data.player_id | 1 | NULL |
| 2 | SUBQUERY | w | ref | world | world | 767 | const | 1 | Using where; Using index |
+----+-------------+------------+--------+----------------+----------+---------+--------------------------------+--------+------------------------------------+
如果刪除了world
條件,這將不再匹配location
索引而是使用epoch
索引。令人驚訝的是,它返回(0.31秒)11088行
9.77秒與0.31秒太大的差別,不容忽視。我不明白爲什麼我在使用location
索引的其他查詢中看不到這樣的性能表現,但更重要的是,我不知道我能做些什麼來解決這個問題。
如果你刪除'w.world ='world'',你不會得到一個子查詢返回多行的錯誤嗎? –
你是說當你沒有使用子查詢時,它返回的結果集更快'(SELECT w.world_id FROM prism_worlds w WHERE w.world ='world')'? – AgRizzo
爲什麼你需要在這裏加入 - '選擇w.world_id從prism_worlds w在哪裏w.world ='world''? – Vishal