加速这个JOIN,MySQL

时间:2011-09-27 21:37:54

标签: mysql optimization

这与我发布的另一个问题相似,但有人告诉我要拆分它们。

我有一个InnoDB MYSQL表,它存储一个多选名称(或表中调用的'code'),一个父对象的id(parent_id)以及在多选(name_id)中选择的选项的名称: / p>

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. 是否有任何索引无效?
  3. 以上查询的EXPLAIN: enter image description here

    非常感谢你!我正在寻找关于从这些表中获得最佳性能的方法的建议。

1 个答案:

答案 0 :(得分:1)

对于你的v2_CA_venues表,我看到你有一个索引ON(城市,状态)。在查询中使用此作为FIRST。您的地图表可以有1000个条目,但是单个“城市+状态”的数量是多少......更不用说了。现在,在查询的顶部将有助于优化其余部分。使用关键字“STRAIGHT_JOIN”会告诉优化器按照您说明的顺序执行此操作。

您拥有3way_unique索引的索引,我会更改(或添加另一个索引),其中最小元素作为索引中的第一个位置...我实际上会将顺序更改为(parent_id,name_id ,代码)。你可以有100个代码,但是有1000个parent_ids。但是现在,你正在寻找一个可能有多个代码的特定父ID ...所以现在,你的索引将只有ex: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'