我有三个名为Item,Event和Seat的表,构造如下:
物品
Id(int)
EventId(int)
Section(int)
活动
Id(int)
VenueId(int)
配置(int)
HOME_TEAM(INT)
座椅
Id(int)
VenueId(int)
配置(int)
Section(int)
我使用以下查询来选择与特定主队相关联的所有项目:
SELECT Item.Id
FROM Item
JOIN Event
ON Event.Id = Item.EventId
JOIN Seat USING (VenueId, Configuration)
WHERE Seat.Section = Item.Section
AND Event.Home_team IN (1,2,3,4)
此查询运行速度非常快 - 仅供参考,大约0.6秒。然而,当我在最后一行的IN子句中添加额外的参数时:
AND Event.Home_team IN (1,2,3,4,5)
......它的速度变得非常慢 - 作为参考,需要大约24秒。
我试过改变IN子句中的不同参数,它们是什么并不重要;事情总是快速运行,最多四个,但一旦我添加第五个,它会慢得多。 Event.Home_team字段已编入索引。我也尝试用这种形式替换最后一行:
AND (Event.Home_team = 1 OR Event.Home_team = 2 OR Event.Home_team = 3 OR Event.Home_team =4 OR Event.Home_team =5)
我发现,对于这个,当有四个选项时,事情会很快运行,但是一旦我添加了五个选项,事情会很慢。
这似乎很奇怪。谁能告诉我它为什么会发生?
修改
评论者要求我的EXPLAIN声明。这是:
**id select_type table type possible_keys keys key_len ref rows Extra**
1 SIMPLE seat ref seat_FI_1,seat_FI_2,section.. exclude 4 const 17147
1 SIMPLE event ref PRIMARY,home_team,configuration_id, VenueId VenueId 5 seat.VenueId 1 Using where
1 SIMPLE item ref FI_2,item_FI_3 FI_2 5 event.id 12 Using where
另外,我应该注意到WHERE语句中有一个附加条款,我最初为了简单起见而遗漏了这个条款:
Seat.exclude = 0
排除可以设置为0或1.它也被编入索引。
答案 0 :(得分:1)
尝试通过SectionID将Seat ID加入Item表,并使用场地和配置的WHERE子句。
SELECT Item.Id
FROM Item
JOIN Event
ON Event.Id = Item.EventId
JOIN Seat
ON Seat.Section = Item.Section
WHERE Event.Configuration = Seat.Configuration
AND Event.Venue = Seat.Venue
AND Event.Home_team IN (1,2,3,4,5)
确保所有EventID和Section字段都有索引。在Section,Configuration和Home_team字段上有索引也不会有任何影响。
答案 1 :(得分:1)
也许第五个值会让MySQL获取更多行(如果你的数据分布严重偏向于Home_team。)或者它可能只是一些记录,但它足以让MySQL决定使用另一个查询计划,并且其他查询计划可能效率低下。
首先,如果您的索引统计信息不正确,请对所涉及的所有表运行ANALYZE TABLE(或OPTIMIZE TABLE)。然后比较两个查询的EXPLAIN,快速和慢速查询。