如何使用连接改进此 MySQL 查询?

How to improve this MySQL Query using join?

我有一个简单的查询,它需要超过 14 秒。

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

注意:count(e.id) 代表调试目的的缩写。事实上我们从两个表中都得到了信息。

解释给出了这个:

+----+-------------+-------+-------------+--------------------------------------------------------------------------------------+--------------------------+---------+-----------------+------+--------------------------------------------------------+
| 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                                            |
+----+-------------+-------+-------------+--------------------------------------------------------------------------------------+--------------------------+---------+-----------------+------+--------------------------------------------------------+

我在 e.id、e.date、e.someid 以及 v.id、v.country、v.city 和 v.region.

我知道数据库设置一团糟,但这就是我现在必须处理的问题。

为什么 SQL 需要这么长的时间,因为最后会有大约。数150?在活动中大约有 100 万个条目,在场馆中大约有 10 万个条目。

两个表都是MyISAM。有什么改进方法吗?

创建这样的索引后

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

需要20秒,解释是这样的:

+----+-------------+-------+------+--------------------------------------+--------------+---------+-------------------+------+------------------------------------+
| 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                        |
+----+-------------+-------+------+--------------------------------------+--------------+---------+-------------------+------+------------------------------------+

您有 left join venues,但您在连接的 venues 行的 where 子句中有条件,因此只会返回连接的行。然而,这是一个附带问题 - 请继续阅读,了解为什么您根本不需要加入。

接下来,如果城市是 vancouver,则无需 测试国家或州。

最后,如果您要查找 "how many future events are in Vancouver",则不需要连接,因为场地 ID 是常量!

试试这个:

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

Mysql 将使用 venueid 上的索引,而无需使用提示。如果没有,执行这个:

analyze events

这将更新索引列中数据分布的统计信息。请注意,如果您的许多活动都在温哥华, 使用索引会更有效(因为无论如何都必须访问大部分行)。

这将使查询的第一部分更快:

INDEX(city, region, country)

我采用了另一种方式,因为 MySQL 似乎无法有效处理连接:

  • 创建了一个新的大 table,其中包含我需要的所有列,来自 join
  • 现在研讨会和活动合二为一table
  • 已添加索引

现在查询很快了。不知道为什么...

从 25 秒,我们减少到 .08 秒

这就是我想要的。

如果还有人知道原因,欢迎您提供答案。