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'