如何使用连接改进此 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 秒
这就是我想要的。
如果还有人知道原因,欢迎您提供答案。
我有一个简单的查询,它需要超过 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 秒
这就是我想要的。
如果还有人知道原因,欢迎您提供答案。