1

私はSQLの専門家ではありません。助けてください。このクエリを最適化するにはどうすればよいですか?

インデックスはありません。master_tableというテーブルとその他のテーブルだけです。同じ結果を得るには、このクエリを最適化する必要があります。必要に応じてインデックスを作成できますが、作成テーブルを変更することはできません。

select month(date_hour), passenger, nationality, passport, airline,
   count(*) N_Viagens
from masterTable
group by month(date_hour), passenger, airline, nationality, passport 
having count(*) > 10

次はテーブルを作成するためのコードですが、そのコードを編集することはできません。クエリまたはインデックスの作成のみです。

select
p.birthdate, p.gender, p.passport, p.name + ' ' + p.surname passenger, p.nationality,
    r.class, r.flightNR, r.payment, r.ticketNR,
    f.src_AP_ID, f.dest_AP_ID, f.AL_ID, f.date_hour, f.AirCrft_Code,ac.manufacturer, ac.model,
    SA.City 'Origin City', SA.Country 'Origin Country', SA.Name 'Origin Airport', 
    DA.City 'Dest City', DA.Country 'Dest Country', DA.Name 'Dest Airport',
    al.Name airline, al.IATA, al.icao
into masterTable 
from passenger p
join reservation r on r.passport = p.passport
join flight f on f.flightNR = r.flightNR
join airport SA on f.src_AP_ID = SA.AP_Id 
join airport DA on f.dest_AP_ID = DA.AP_Id 
join aircraft ac on f.airCrft_Code = ac.code
join airline al on f.AL_ID = al.AL_ID 

インデックスなし:

SQL Server Execution Times: CPU time = 10125 ms,  elapsed time = 17052 ms.

人々私はそれをやったと思います、あなたのすべてに感謝します、もう一度ありがとう

私は次のようにインデックスを作成しました:

create index idx_MasterTable_Passenger on masterTable(passport, airline)

そして私がこれに変更したクエリ:

select month(date_hour), max(passenger) as passenger, nationality, passport, airline, count(*) N_Viagens
from masterTable
group by airline, nationality, passport, month(date_hour)
having count(*) > 10

あなたはどう思いますか、それは受け入れられますか?

SQL Server Execution Times: CPU time = 8362 ms,  elapsed time = 5721 ms.

彼がこれに同意するなら、私は先生と話します

先生はこの変更を受け入れませんでした。テーブルやクエリを変更することはできず、適切なインデックスを作成するだけです。

4

4 に答える 4

1

month(date_hour)これは注意が必要な方法です。グループ化を実際に高速化するには、その正確な式に機能インデックス(MS SQL Serverの計算列のインデックス)が必要です。インデックスを付けるだけでは十分でdate_hourはありません。

このでは、2番目のテーブルには計算列とインデックスがあります(最初のテーブルにはどちらもありません)。同一のクエリの実行プランが異なることに注意してください。最初のクエリは実際にデータを並べ替え、2番目のクエリはインデックスを処理します。

これは宿題なので、自分で例に取り入れましょう。

ところで、インデックスとパフォーマンスのトピックに興味がある場合は、「インデックスを使用してください、ルーク!」を読むことを強くお勧めします。

于 2012-05-29T19:20:37.697 に答える
0

このクエリには常にスキャンが必要です。WHERE句が追加されたため、小さなサブセットをすばやく分離してクエリを高速化することはできません。HAVING句がありますが、これは集約後にのみ適用できます。

ただし、GROUPBY句があります。GROUP BY句の集計は、適切なインデックスを追加することで高速化できます。GROUP BY句の列もSELECTリストで使用されるため、テーブル全体ではなく、そのインデックスのみをスキャンする必要があることを実現できます。

GROUP BY句には、month(date_hour)という式が含まれています。これは、インデックスではこれを無視できることを意味します。乗客、航空会社、国籍、パスポートのままです。インデックスを作成する前に、正しい順序を理解する必要があります。私の勘では、最も選択的な列を最初に配置する必要があります。つまり、一意の値の数が最も少ない列の前に、一意の値の数が最も多い列を表示する必要があります。乗客、航空会社、国籍、パスポートの注文はすでにかなり良いと思います。とはいえ、列の順序を変更して少し実験します。

インデックスを作成したら、クエリを書き直す必要はありません。ただし、RDBMSのオプティマイザが(MySQLのように)ナイーブである場合は、月(date_hour)式をGROUPBY句の最後の式として配置する必要があります。これは、行が返される順序に影響を与える可能性がありますが、結果を変更することはありません。ただし、それはまったく問題ではありません(問題がある場合は、ORDER BY句を追加する必要があります)

于 2012-05-29T19:20:19.223 に答える
0

MasterTableには何が含まれていますか?乗客用のフライトセグメントのようなものが含まれているようです。もしそうなら、月に10回以上飛ぶ乗客はほとんどいません。

次の手順を実行すると、パフォーマンスを向上させることができる場合があります。

(1)MasterTableで乗客のインデックスを作成します。

create index idx_MasterTable_Passenger on MasterTable(Passenger);

(2)10回飛ぶ人は他の人に比べてまれであることを認識し、それらを除外します。

select month(date_hour), passenger, nationality, passport, airline,
       count(*) as N_Viagens
from masterTable
where passenger in (select passenger from MasterTable group by passenger having count(*) >= 10)
group by month(date_hour), passenger, airline, nationality, passport
having count(*) > 10  

これにより、クエリが高速化される可能性があります。

ただし、少し違うことをお勧めします。このような質問に答えるために、乗客(または同様のレベル)ごとの情報を要約したテーブルを作成します。新しいデータがメインテーブルに追加されたら、このテーブルに行を更新または挿入します。

たとえば、、、の構造を持つサマリーテーブルが必要な場合があります。このクエリを夜間または週に1回実行すると、多くの質問に答えられる可能性があります。

于 2012-05-29T18:53:12.883 に答える
0

パスポートは名前よりも優れた識別子であるように見えます。多くの人が名前を変えたという事実を考慮に入れてください。

パスポート、航空会社のインデックスを作成する

インデックスを国籍、パスポート、航空会社、乗客に拡張することはできますが、どれだけ購入するかわかりませんか?

select nationality, passport, airline, year(date_hour), month(date_hour), max(passenger), count(*) N_Viagens
from masterTable 
group by  nationality, passport, airline, year(date_hour), month(date_hour) 
having count(*) > 10
于 2012-05-29T19:41:30.950 に答える