次のデータベース構造があります。
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
このクエリをできるだけ速く実行するにはどうすればよいですか?インデックスを使用する必要がありますか?もしそうなら、どのテーブルのどの列にインデックスを付ける必要がありますか?
これが私のクエリプランの写真です:
おかげで、
インデックスはどのデータベースにも不可欠です。
「素人」の言葉で言えば、インデックスは...まあ、まさにそれです。インデックスは、2つのものを格納する2番目の非表示のテーブルと考えることができます。
インデックスの作成に関するいくつかの経験則:
where
条件を実行するすべてのフィールドにインデックスを作成します。double
フィールドにインデックスを作成しないでください。varchar
フィールドにインデックスを作成しないでください。これを読むことをお勧めします: http://dev.mysql.com/doc/refman/5.5/en/using-explain.html
最初にJOINSを確認する必要があります。インデックスの最も明白な2つの候補は、AccountMapper.AccountingAccount
とChannelMapper.AccountingChannel
です。
Shipments.MarketPlace
、Shipments.ShipmentChannel
およびShipments.Component
のインデックス作成も検討する必要があります。
ただし、インデックスを追加すると、インデックスを維持するためのワークロードが増加します。このクエリではパフォーマンスが向上する可能性がありますが、テーブルの更新が許容できないほど遅くなることがあります。いずれにせよ、MySQLオプティマイザは、テーブルのフルスキャンがインデックスによるアクセスよりも速いと判断する場合があります。
これを行う唯一の方法は、最良の結果をもたらすと思われるインデックスを設定し、システムをベンチマークして、他の場所でパフォーマンスを低下させずに、ここで希望する結果が得られることを確認することです。 [〜#〜] explain [〜#〜] ステートメントをうまく活用して、何が起こっているのかを確認し、自分またはオプティマイザが小さなテーブルに対して行った最適化は、同じ最適化ではない可能性があることを覚えておいてくださいより大きなもので必要になるでしょう。
他の3つの回答はインデックスがカバーされているようですので、これはインデックスに追加されます。 where句がないため、常にdarnデータベース全体を選択しています。実際、データベースの設計には、出荷日など、この点で役立つものはありません。それについて考えてください。
これも持っています:
join (select Component, sum(amount) from Shipment group by component) as Totals
on Shipment.Component = Totals.Component
それで十分ですが、このサブクエリから何も選択しません。したがって、なぜそれを持っているのですか? sum(amount)などを選択したい場合は、select句で使用できるようにエイリアスを指定する必要があります。