パフォーマンスの調整が必要なクエリまたはストアドプロシージャがある場合、最初に試すことは何ですか。
パフォーマンスの調整が必要なクエリまたはストアドプロシージャがある場合、最初に試すことは何ですか。
回答:
これは、最適化について尋ねる人にいつも私が与えるものの便利なリストです。
私たちは主にSybaseを使用していますが、ほとんどのアドバイスは全体に適用されます。
たとえば、SQL Serverには多数のパフォーマンスモニタリング/チューニングビットが付属していますが、そのようなものがない場合は(そうした場合でも)、次のことを検討します...
私が見た問題の99%は、結合に入れたテーブルが多すぎることが原因です。これに対する修正は、結合の半分を(いくつかのテーブルで)実行し、結果を一時テーブルにキャッシュすることです。次に、その一時テーブルで結合する残りのクエリを実行します。
#temp
テーブルは@table
、大量(数千行)の変数よりもはるかに優れたパフォーマンスを発揮します。トピックからわずかに外れていますが、これらの問題を制御できる場合...
高レベルおよび高影響。
CREATE INDEX
WHERE
and JOIN
句で使用できるインデックスがあることを確認します。これにより、データアクセスが大幅に高速化されます。
環境がデータマートまたはウェアハウスである場合、考えられるほとんどすべてのクエリに対してインデックスが豊富である必要があります。
ではトランザクション環境そのインデックスのメンテナンスがリソースを下にドラッグしないように、インデックスの数は下とその定義より戦略的でなければなりません。(インデックスのメンテナンスとは、INSERT, UPDATE,
およびDELETE
操作の場合と同様に、基になるテーブルの変更を反映するためにインデックスのリーフを変更する必要がある場合です。)
また、インデックス内のフィールドの順序にも注意してください。フィールドの選択性が高い(カーディナリティが高い)ほど、インデックスの最初の方に表示されます。たとえば、中古車をクエリしているとします。
SELECT i.make, i.model, i.price
FROM dbo.inventory i
WHERE i.color = 'red'
AND i.price BETWEEN 15000 AND 18000
価格は通常、カーディナリティが高くなります。数十色しかないかもしれませんが、おそらく数千の異なる希望価格があります。
これらのインデックスの選択のうちidx01
、クエリを満たすためのより高速なパスを提供します。
CREATE INDEX idx01 ON dbo.inventory (price, color)
CREATE INDEX idx02 ON dbo.inventory (color, price)
これは、色の選択よりも価格ポイントを満たす自動車の数が少なくなり、クエリエンジンが分析するデータがはるかに少なくなるためです。
私は、クエリを高速化するために、フィールドの順序のみが異なる2つの非常に類似したインデックス(firstname、lastname)と(lastname、firstname)をもう1つ持つことが知られています。
私が最近学んだトリックは、SQL Serverがupdateステートメントでフィールドだけでなくローカル変数も更新できることです。
UPDATE table
SET @variable = column = @variable + otherColumn
またはより読みやすいバージョン:
UPDATE table
SET
@variable = @variable + otherColumn,
column = @variable
これを使用して、再帰的な計算を実装するときに複雑なカーソル/結合を置き換え、パフォーマンスも大幅に向上しました。
パフォーマンスを大幅に改善した詳細とサンプルコードを以下に示します 。 aspx
ここでMySQLを想定し、EXPLAINを使用してクエリで何が行われているのかを調べ、インデックスが可能な限り効率的に使用されていることを確認し、ファイルの並べ替えを排除します。高性能MySQL:最適化、バックアップ、レプリケーションなどは、MySQLパフォーマンスブログと同様に、このトピックに関する優れた書籍です。
@Terrapin isnullと合体の間には、言及する価値のある他のいくつかの違いがあります(ANSI準拠は私にとって大きなものです)。
通常は、結合から始めます。1つずつクエリから除外し、クエリを再実行して、問題のある特定の結合があるかどうかを確認します。
常にバインド変数を使用することを習慣にしています。RDBMSがSQLステートメントをキャッシュしない場合、バインド変数が役に立たない可能性があります。ただし、バインド変数を使用しない場合、RDBMSはクエリ実行プランと解析済みSQLステートメントを再利用する機会がありません。大幅な節約になる可能性があります:http : //www.akadia.com/services/ora_bind_variables.html。私は主にOracleを使用していますが、Microsoft SQL Serverはほとんど同じように動作します。
私の経験では、バインド変数を使用しているかどうかわからない場合は、おそらく使用していません。アプリケーション言語がそれらをサポートしていない場合は、サポートしている言語を見つけてください。クエリBのバインド変数を使用して、クエリAを修正できる場合があります。
その後、私はDBAと話し合って、RDBMSに最も苦痛を与えている原因を突き止めます。「なぜこのクエリは遅いのですか?」と尋ねるべきではないことに注意してください。それはあなたの医者にあなたに虫垂を取り出すように頼むようなものです。確かにクエリに問題がある可能性がありますが、何か他の問題が発生している可能性もあります。開発者として、私たちはコード行の観点から考える傾向があります。ラインが遅い場合は、そのラインを修正します。しかし、RDBMSは非常に複雑なシステムであり、遅いクエリははるかに大きな問題の症状である可能性があります。
あまりにも多くのSQLチューニングのヒントはカーゴカルトアイドルです。ほとんどの場合、問題は使用する構文とは無関係または最小限に関連しているので、通常、できるだけクリーンな構文を使用するのが最善です。次に、データベース(クエリではない)を調整する方法を検討します。それが失敗したときにのみ構文を微調整します。
パフォーマンスチューニングと同様に、常に意味のある統計を収集します。調整しているユーザーエクスペリエンスでない限り、ウォールクロック時間を使用しないでください。代わりに、CPU時間、フェッチされた行、ディスクから読み取られたブロックなどを確認します。多くの場合、人々は間違ったことを最適化します。
NOT INクエリを可能であればLEFT OUTER JOINSに変換します。たとえば、Table2の外部キーで使用されていないTable1のすべての行を検索する場合は、次のようにします。
SELECT *
FROM Table1
WHERE Table1.ID NOT IN (
SELECT Table1ID
FROM Table2)
しかし、これによりはるかに優れたパフォーマンスが得られます。
SELECT Table1.*
FROM Table1
LEFT OUTER JOIN Table2 ON Table1.ID = Table2.Table1ID
WHERE Table2.ID is null
SET NOCOUNT ON
通常、実際にを使用する必要がない限り、ストアドプロシージャ内の最初の行@@ROWCOUNT
。
SQL Serverでは、nolockディレクティブを使用します。これにより、待機せずにselectコマンドを完了することができます。通常、他のトランザクションは完了します。
SELECT * FROM Orders (nolock) where UserName = 'momma'
必要のない場所でカーソルを削除します。
使いたい
isnull(SomeColThatMayBeNull, '')
以上
coalesce(SomeColThatMayBeNull, '')
合体が与える複数の引数のサポートが必要ない場合。
http://blog.falafel.com/2006/04/05/SQLServerArcanaISNULLVsCOALESCE.aspx
システムプロシージャはすべて "sp_"で始まるため、ストアドプロシージャ名の前に "sp_"を付けないでください。SQLServerは、呼び出されたときにプロシージャを見つけるために検索をより困難にする必要があります。
ダーティリード -
set transaction isolation level read uncommitted
トランザクションの整合性が絶対に必要ではないデッドロックを防止します(通常はそうです)