我有以下数据库结构:
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
如何让此查询尽可能快地运行?我应该使用索引吗?如果是这样,我应该将哪些表的哪些列编入索引?
以下是我的查询计划图片:
谢谢,
答案 0 :(得分:24)
索引对任何数据库都至关重要。
用“外行”术语来说,索引是......好吧,恰恰相反。您可以将索引视为存储两件事的第二个隐藏表:排序数据和指向其在表中位置的指针。
创建索引的一些拇指规则:
where
条件的每个字段上创建索引。double
字段上创建索引,除非绝对必要。varchar
字段上创建索引,除非绝对必要。我建议你阅读:http://dev.mysql.com/doc/refman/5.5/en/using-explain.html
答案 1 :(得分:3)
你的JOINS应该是第一个看的地方。索引的两个最明显的候选者是AccountMapper.AccountingAccount
和ChannelMapper.AccountingChannel
。
您还应该考虑为Shipments.MarketPlace
,Shipments.ShipmentChannel
和Shipments.Component
编制索引。
但是,添加索引会增加维护它们的工作量。虽然它们可能会对此查询提供性能提升,但您可能会发现更新表变得非常缓慢。在任何情况下,MySQL优化器可能会决定对表的完整扫描比通过索引访问它更快。
实际上,唯一的方法是设置似乎能给你最好结果的索引,然后对系统进行基准测试,以确保你在这里得到你想要的结果,同时不影响其他地方的性能。充分利用EXPLAIN语句来了解正在发生的事情,并记住您自己或优化器在小表上进行的优化可能与您在较大表上所需的优化不同。
答案 2 :(得分:2)
其他三个答案似乎涵盖了索引,所以这是索引的补充。你没有where子句,这意味着你总是选择整个数据库。实际上,您的数据库设计在这方面没有任何用处,例如发货日期。想一想。
你也有这个:
join (select Component, sum(amount) from Shipment group by component) as Totals
on Shipment.Component = Totals.Component
这一切都很好但你没有从这个子查询中选择任何东西。那为什么你呢?如果你确实想要选择一些东西,比如总和(金额),你必须给它一个别名,使其在select子句中可用。