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

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

「素人」の言葉で言えば、インデックスは...まあ、まさにそれです。インデックスは、並べ替えられたデータと、テーブル内のその位置へのポインターという 2 つのものを格納する 2 番目の非表示のテーブルと考えることができます。

索引の作成に関するいくつかの経験則:

  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 を最初に確認する必要があります。インデックスの最も明白な 2 つの候補はAccountMapper.AccountingAccountChannelMapper.AccountingChannelです。

インデックス作成も検討する必要がShipments.MarketPlaceありShipments.ShipmentChannelますShipments.Component

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

実際にこれを行う唯一の方法は、最良の結果が得られるように見えるインデックスを設定し、システムのベンチマークを行って、他の場所のパフォーマンスを犠牲にせずに、ここで必要な結果が得られていることを確認することです. EXPLAINステートメントをうまく利用して、何が起こっているかを調べてください。小さなテーブルで自分自身またはオプティマイザーが行った最適化は、大きなテーブルで必要な最適化と同じではない可能性があることを覚えておいてください。

于 2013-06-27T22:59:05.570 に答える
2

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

これもあります:

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 に答える