12

我有以下数据库结构:

create table Accounting
(
  Channel,
  Account
)

create table ChannelMapper
(
  AccountingChannel,
  ShipmentsMarketPlace,
  ShipmentsChannel
)

create table AccountMapper
(
  AccountingAccount,
  ShipmentsComponent
)

create table Shipments
(
   MarketPlace,
   Component,
   ProductGroup,
   ShipmentChannel,
   Amount
 )

我在这些表上运行了以下查询,我正在尝试优化查询以尽可能快地运行:

 select Accounting.Channel, Accounting.Account, Shipments.MarketPlace
 from Accounting join ChannelMapper on Accounting.Channel = ChannelMapper.AccountingChannel

 join AccountMapper on Accounting.Accounting = ChannelMapper.AccountingAccount
 join Shipments on 
 (
     ChannelMapper.ShipmentsMarketPlace = Shipments.MarketPlace
     and ChannelMapper.AccountingChannel = Shipments.ShipmentChannel
     and AccountMapper.ShipmentsComponent = Shipments.Component
 )
 join (select Component, sum(amount) from Shipment group by component) as Totals
    on  Shipment.Component = Totals.Component

如何使此查询尽可能快地运行?我应该使用索引吗?如果是这样,我应该索引哪些表的哪些列?

这是我的查询计划的图片:

在此处输入图像描述

谢谢,

4

3 回答 3

26

索引对于任何数据库都是必不可少的。

用“外行”的话来说,索引是……嗯,正是如此。您可以将索引视为第二个隐藏的表,它存储两件事:已排序的数据和指向其在表中位置的指针。

创建索引的一些经验法则:

  1. 在连接中(或将要)使用的每个字段上创建索引。
  2. 在要执行频繁where条件的每个字段上创建索引。
  3. 避免在所有内容上创建索引。在每个表的相关字段上创建索引,并使用关系来检索所需的数据。
  4. 避免在double字段上创建索引,除非绝对必要。
  5. 避免在varchar字段上创建索引,除非绝对必要。

我建议您阅读以下内容: http: //dev.mysql.com/doc/refman/5.5/en/using-explain.html

于 2013-06-27T22:59:19.777 回答
3

您的 JOINS 应该是第一个查看的位置。索引的两个最明显的候选者是AccountMapper.AccountingAccountChannelMapper.AccountingChannel

您应该考虑 indexing Shipments.MarketPlaceShipments.ShipmentChannel以及Shipments.Component

但是,添加索引会增加维护它们的工作量。虽然它们可能会提高此查询的性能,但您可能会发现更新表变得慢得令人无法接受。在任何情况下,MySQL 优化器都可能决定对表进行全扫描比通过索引访问它更快。

真正做到这一点的唯一方法是设置看起来能给你最好结果的索引,然后对系统进行基准测试,以确保你在这里得到你想要的结果,同时不影响其他地方的性能。充分利用EXPLAIN语句找出发生了什么,并记住您自己或优化器对小表所做的优化可能与您在大表上需要的优化不同。

于 2013-06-27T22:59:05.570 回答
2

其他三个答案似乎涵盖了索引,因此这是对索引的补充。您没有 where 子句,这意味着您总是选择整个该死的数据库。事实上,您的数据库设计在这方面没有任何用处,例如发货日期。考虑一下。

你也有这个:

join (select Component, sum(amount) from Shipment group by component) as Totals
on  Shipment.Component = Totals.Component

这一切都很好,但是您没有从这个子查询中选择任何东西。因此,你为什么拥有它?如果您确实想要选择某些内容,例如 sum(amount),则必须为其提供别名以使其在 select 子句中可用。

于 2013-06-27T23:11:08.520 回答