How to improve this MySQL Query using join?

偶尔善良 提交于 2019-12-20 02:57:06

问题


I have got a simple query and it takes more than 14 seconds.

select 
     e.title, e.date, v.name, v.city, v.region, v.country

from seminar e force index for join (venueid) 
     left join venues v on e.venueid = v.id 

where v.country = 'US'
     and v.city = 'New York' 
     and v.region = 'NY'
     and e.date > curdate() 
     and e.someid != 0

Note: count(e.id) stands for an abbreviation for debugging purposes. In fact we get information from both tables.

Explain gives this:

+----+-------------+-------+-------------+--------------------------------------------------------------------------------------+--------------------------+---------+-----------------+------+--------------------------------------------------------+
| id | select_type | table | type        | possible_keys                                                                        | key                      | key_len | ref             | rows | Extra                                                  |
+----+-------------+-------+-------------+--------------------------------------------------------------------------------------+--------------------------+---------+-----------------+------+--------------------------------------------------------+
|  1 | SIMPLE      | v     | index_merge | PRIMARY,city,country,region | city,region | 378,378 | NULL            |    2 | Using intersect(city,region); Using where |
|  1 | SIMPLE      | e     | ref         | venueid                     |  venueid    | 5       | v.id            |   11 | Using where                                            |
+----+-------------+-------+-------------+--------------------------------------------------------------------------------------+--------------------------+---------+-----------------+------+--------------------------------------------------------+

I have indexes on e.id, e.date, e.someid, as well as v.id, v.country, v.city and v.region.

I know the db-setup is a mess but that's what I have to deal with right now.

Why does the SQL take so long as in the end there will be an approx. count 150? In events there are about 1M entries and in venues about 100K.

Both tables are MyISAM. Any ideas how to improve this?

Upon creating an index like this

create index location on venues (city, region, country)

it takes 20 seconds, the explain is this:

+----+-------------+-------+------+--------------------------------------+--------------+---------+-------------------+------+------------------------------------+
| id | select_type | table | type | possible_keys                        | key          | key_len | ref               | rows | Extra                              |
+----+-------------+-------+------+--------------------------------------+--------------+---------+-------------------+------+------------------------------------+
|  1 | SIMPLE      | v     | ref  | PRIMARY,city,country,region,location | location     | 765     | const,const,const |  410 | Using index condition; Using where |
|  1 | SIMPLE      | e     | ref  | EventVenueID                         | venueid      | 5       | v.id              |   11 | Using where                        |
+----+-------------+-------+------+--------------------------------------+--------------+---------+-------------------+------+------------------------------------+

回答1:


You have left join venues, but you have conditions in the where clause on the joined venues row, so only joined rows will be returned. However, that's a side issue - read on for why you don't need a join at all.

Next, if the city is vancouver, there's no need to also test for country or state.

Finally, if you're trying to find "how many future events are in Vancouver", you don't need a join, as the venue id is a constant!

Try this:

select count(*) as event_count
from events
where venueid = (select id from venues where city = 'vancouver')
and startdate > curdate() 
and te_id != 0

Mysql will use the index on venueid without you having to use a hint. If it doesn't, execute this:

analyze events

which will update the statistics of the data distribution in the indexed columns. Note that if a lot of your events are in Vancouver, it's more efficient to not use an index (as most of the rows will have to be accessed anyway).




回答2:


This would make the first part of the query faster:

INDEX(city, region, country)



回答3:


I went another way since it seems that MySQL can't handle joins effectively:

  • Created one big new table with all the columns I need from the join
  • So the seminars and events are in one table now
  • added indexes

Now the query is fast. Don't know why...

From 25 seconds, we are down to .08 seconds

That's how I wanted it.

If anybody still knows why, you are more than welcome to provide an answer.



来源:https://stackoverflow.com/questions/31150650/how-to-improve-this-mysql-query-using-join

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!