Speed up this JOIN, MySQL
This is similar to another question I posted, but I was told to split them.
I have a InnoDB MYSQL table that stores a multi select name ( or 'code' as the table calls it), a parent object's id (parent_id) and the name of the option selected in the multi select (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 ;
and a simple table to store the names (i figured i would show this because its used in the query):
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 ;
That I would like to optimize for the following query:
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'
- Are the indexes placed on the table offering the best performance for these Joins and WHEREs?
- Are any of the indexes useless?
The EXPLAIN for the 开发者_如何学Goabove query:
Thank you so much! I am looking for advice on the way to get the best performace out of these tables.
FOR your v2_CA_venues table, I see you have an index ON( City, Status ). Use this as the FIRST IN your query. Your maps table could have 1000's of entries, but how many for a single "City + Status"... much less. So now that at the top of your query will help optimize the rest. Using the keyword "STRAIGHT_JOIN" tells optimizer to do it in the order you've stated.
What you have of an index of 3way_unique
index, I would change (or add another index) with the smallest element as first position in the index... I would actually change the order to ( parent_id, name_id, code ). You could have 100 codes, but 1000's of parent_ids. But now, you are looking for a specific parent ID that could have multiple codes... So now, your index would be down to just ex: the ONE Parent_ID and it may have 8 codes and you are looking for 3. You've just reduced your comparison set for the join.
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'
精彩评论