2015-09-09 85 views
2

我修改我这是刚刚从预订拉动保留原始查询表加入到单位它连接到建筑的表,以检索每个建筑物的名称和单元编号表预订。优化此双左连接查询?

我为此创建了一个SQLFiddle,并在查询前加上了解释。 Per @Alex,我在bookings.unit_number上添加了一个索引,它在SQLFiddle中是bookings.external_system_id。 (忽略次要栏位)。

当我为所有预订完全导出时,仍然需要一些时间(分钟)。我只是试图尽可能优化这一点,因为我意识到完全导出仍然需要一段时间(总计13019077个结果)。

+2

如果你没有使用'units'中的任何一列,为什么'join'? –

+0

顺便说一下,我在EXPLAIN前面加了SELECT,但它对我来说并不重要。 –

+1

@vkp - 添加从建筑物表中提取数据的最终查询。 –

回答

4

你正在处理一个复杂的SQL方面。你可能想读http://use-the-index-luke.com

恕我直言,你的发言

有日期范围和属性过滤器,但这些都是可选的

很可能让你从我们这里得到完全的任何意见除非您向我们展示这些过滤器的外观,否则毫无价值。但是,我仍然会尽力提供帮助。

units (unit_number, id)buildings(id,name)上创建化合物covering indexes并查看性能是否提高。这些复合指标应该有助于业绩。如果您在bookings.arrival上过滤,那么您也可以为了同样的目的在bookings (arrival, unit_number)上创建复合索引。

在InnoDB中,将主键作为复合索引的最后一列没有意义; MySQL在每个索引中放置相应的对象。 在MyISAM你应该把PK放在那里,如果你的查询需要它。以主键开头或包含它的复合索引仍然可能有用。

单列索引的集合无法达到与精心挑选的复合索引相同的目的。拥有大量索引会增加查询计划程序为给定查询找到有用的索引的几率。但是,覆盖为您的查询设计的索引可以从根本上加快速度。

索引消耗的空间与其包含的数据量非常大致成正比。硬盘空间现在是惊人的便宜。

在你的Sql小提琴很显然你应该改变你的units表的索引。摆脱external_system_id上的单列索引并将其替换为该复合索引。

INDEX `units_joindex` (`external_system_id`, `building_id`) 

像这样:(http://sqlfiddle.com/#!9/e5ffd/2/0)。请注意,EXPLAIN结果和查询计划在很大程度上取决于表中的行数和索引。像你这样的查询必然需要拉一张桌子,所以你不会在那里看到很多索引。

+0

@Ollie_Jones - 感谢您的链接。 “请注意,这将消耗更多空间,并且插入会减慢” - 您是否知道添加覆盖索引会占用多少“空间”?使用多个单一索引与组合索引是否“更安全”?目前这些表使用单个索引。 –

+0

也,因为id已经是一个PK,它不应该包含在组合索引或应该? –

+0

请参阅我的编辑。请花时间阅读使用索引卢克。 –