2011-09-27 40 views
2

這與我發佈的另一個問題類似,但我被告知需要拆分它們。加快這個JOIN,MySQL

我有一個InnoDB MYSQL表,它存儲了一個多重選擇名稱(或表中稱之爲「代碼」),一個父對象的id(parent_id)以及在多重選擇(name_id)中選擇的選項名稱:

CREATE TABLE IF NOT EXISTS `v2_CA_venue_option_map` (
    `map_id` int(11) NOT NULL auto_increment, 
    `code` varchar(30) NOT NULL, 
    `parent_id` int(11) NOT NULL, 
    `name_id` int(11) NOT NULL, 
    PRIMARY KEY (`map_id`), 
    UNIQUE KEY `3way_unique` (`code`,`parent_id`,`name_id`), 
    KEY `name_id` (`name_id`), 
    KEY `filter` (`code`,`name_id`), 
    KEY `parent_id` (`parent_id`), 
    KEY `code` (`code`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=875156 ; 

和一個簡單的表來存儲名字(我想我會證明這一點,因爲它在查詢中使用):

CREATE TABLE IF NOT EXISTS `v2_CA_venue_option_name` (
    `name_id` int(11) NOT NULL auto_increment, 
    `name` varchar(255) NOT NULL, 
    PRIMARY KEY (`name_id`), 
    UNIQUE KEY `name` (`name`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Venue Option Names' AUTO_INCREMENT=60 ; 

CREATE TABLE IF NOT EXISTS `v2_CA_venues` (
    `venue_id` int(11) NOT NULL auto_increment, 
    `status` char(1) NOT NULL, 
    `name` varchar(255) NOT NULL, 
    `url_key` varchar(255) NOT NULL, 
    `city` varchar(255) NOT NULL, 
    PRIMARY KEY (`venue_id`), 
    KEY `city` (`city`,`status`), 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ; 

,我想以優化以下查詢:

SELECT v.name, v.venue_id, v.url_key 
FROM `v2_CA_venue_option_map` map 
JOIN `v2_CA_venue_option_map` map2 ON (map2.parent_id = map.parent_id) 
JOIN `v2_CA_venue_option_map` map3 ON (map3.parent_id = map.parent_id) 
JOIN `v2_CA_venues` v ON (v.venue_id = map.parent_id) 
WHERE v.city = 'Nevada City' 
AND map3.code = 'a_venue_types' 
AND map3.name_id = 19 
AND map.code = 'a_event_types' 
AND map.name_id = 20 
AND map2.code = 'a_event_types' 
AND map2.name_id = 3 
AND v.status = 'a' 
  1. 索引是否放在桌子上爲這些連接和WHERE提供最佳性能?
  2. 是否有任何索引無用?

爲上述查詢的解釋: enter image description here

太謝謝你了!我正在尋找建議,以便從這些表格中獲得最佳表現。

+1

實際上,場地表可能是一個恩人優化查詢...你可以請張貼結構也與它的指標? – DRapp

+0

增加了場地表。 – RonSper

回答

1

對於您的v2_CA_venues表,我看到您的索引ON(城市,狀態)。使用這個作爲你的查詢中的第一個。你的地圖表可以有1000個條目,但是對於單個「城市+狀態」來說有多少... ...少得多。所以現在在查詢的頂部將有助於優化其餘部分。使用關鍵字「STRAIGHT_JOIN」會告訴優化器按照您所述的順序執行此操作。

你有什麼索引3way_unique索引,我會改變(或添加另一個索引)與最小的元素作爲索引中的第一個位置...我實際上會改變順序(parent_id,name_id,code) 。你可以有100個代碼,但有1000個parent_ids。但是現在,您正在尋找一個可能有多個代碼的特定父代ID ...因此,現在,您的索引可能只是前者:ONE Parent_ID,它可能有8個代碼,您正在尋找3。只是減少了連接的比較集。

SELECT STRAIGHT_JOIN 
     v.name, 
     v.venue_id, 
     v.url_key 
    FROM 
     v2_CA_venues v 

     join v2_CA_venue_option_map map 
      ON v.venue_id = map.parent_id 
      AND map.name_id = 20 
      and map.code = 'a_event_types' 

     join v2_CA_venue_option_map map2 
      ON v.venue_id = map2.parent_id 
      AND map2.name_id = 3 
      and map2.code = 'a_event_types' 

     join v2_CA_venue_option_map map3 
      ON v.venue_id = map3.parent_id 
      AND map3.name_id = 19 
      and map3.code = 'a_venue_types' 

    where 
      v.City = 'Nevada City' 
     and v.status = 'a'