web-dev-qa-db-ja.com

SQLクエリを高速化する方法は?インデックス?

次のデータベース構造があります。

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

このクエリをできるだけ速く実行するにはどうすればよいですか?インデックスを使用する必要がありますか?もしそうなら、どのテーブルのどの列にインデックスを付ける必要がありますか?

これが私のクエリプランの写真です:

enter image description here

おかげで、

enter image description here

11
Attilah

インデックスはどのデータベースにも不可欠です。

「素人」の言葉で言えば、インデックスは...まあ、まさにそれです。インデックスは、2つのものを格納する2番目の非表示のテーブルと考えることができます。

インデックスの作成に関するいくつかの経験則:

  1. 結合で使用される(または使用される)すべてのフィールドにインデックスを作成します。
  2. 頻繁にwhere条件を実行するすべてのフィールドにインデックスを作成します。
  3. すべてにインデックスを作成しないでください。すべてのテーブルの関連フィールドにインデックスを作成し、リレーションを使用して目的のデータを取得します。
  4. 絶対に必要でない限り、doubleフィールドにインデックスを作成しないでください。
  5. 絶対に必要でない限り、varcharフィールドにインデックスを作成しないでください。

これを読むことをお勧めします: http://dev.mysql.com/doc/refman/5.5/en/using-explain.html

24
Barranka

最初にJOINSを確認する必要があります。インデックスの最も明白な2つの候補は、AccountMapper.AccountingAccountChannelMapper.AccountingChannelです。

Shipments.MarketPlaceShipments.ShipmentChannelおよびShipments.Componentのインデックス作成も検討する必要があります。

ただし、インデックスを追加すると、インデックスを維持するためのワークロードが増加します。このクエリではパフォーマンスが向上する可能性がありますが、テーブルの更新が許容できないほど遅くなることがあります。いずれにせよ、MySQLオプティマイザは、テーブルのフルスキャンがインデックスによるアクセスよりも速いと判断する場合があります。

これを行う唯一の方法は、最良の結果をもたらすと思われるインデックスを設定し、システムをベンチマークして、他の場所でパフォーマンスを低下させずに、ここで希望する結果が得られることを確認することです。 [〜#〜] explain [〜#〜] ステートメントをうまく活用して、何が起こっているのかを確認し、自分またはオプティマイザが小さなテーブルに対して行った最適化は、同じ最適化ではない可能性があることを覚えておいてくださいより大きなもので必要になるでしょう。

3
user1864610

他の3つの回答はインデックスがカバーされているようですので、これはインデックスに追加されます。 where句がないため、常にdarnデータベース全体を選択しています。実際、データベースの設計には、出荷日など、この点で役立つものはありません。それについて考えてください。

これも持っています:

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

それで十分ですが、このサブクエリから何も選択しません。したがって、なぜそれを持っているのですか? sum(amount)などを選択したい場合は、select句で使用できるようにエイリアスを指定する必要があります。

2
Dan Bracuk