Navicatブログ

よくあるSQLクエリの間違い – パート2 2022年4月26日 Robert Gravelle

パート2: 非SARGableクエリの条件

ほとんどのプログラマーと同様に、データベース開発者は、多かれ少なかれ特定の要求の直接変換であるコードを作成する傾向があります。ほとんどのプログラミング言語(SQLを含む)が人間が読めるように設計されているという事実も、この問題の原因です。なぜこれが懸念事項なのですか?全てのプログラミング言語は、特定の操作を他よりも高速に実行します。リレーショナルデータベースでは、クエリオプティマイザがSQLクエリを分析し、クエリプランと呼ばれる効率的な実行メカニズムを決定します。オプティマイザは、クエリごとに1つ以上のクエリプランを生成します。各プランは、クエリを実行するための1つの可能な方法を示します。最も効率的なクエリプランがその後選択され、クエリの実行に利用されます。結局のところ、リクエストの言語を模倣するSQLが最も効率的なアプローチになることはめったにありません。

よくあるSQLクエリの間違いシリーズの今回の記事では、不十分に記述されたSQLステートメントの1つの例を調査し、効率を高める方法でそれを書き直します。

インデックス付きの列を関数に渡す

データベース開発者のコードで何度も出てくる失敗の1つは、インデックス列を関数に渡すことです。説明のために、varcharのcustomerName列にインデックスがあるこのテーブルに対してクエリを実行してみましょう。

customerName_index (95K)

名前が文字「R」で始まる全ての顧客を取得するように求められた場合、customerName列の最初の文字を返すLEFT()関数を使用する傾向があるかもしれません。

left_query (49K)

残念ながら、インデックス付きのcustomerName列を関数に渡すことにより、クエリエンジンはテーブル内の全ての行の結果を評価しなければなりません。

SARGableクエリ対非SARGableクエリ

リレーショナルデータベースには、Search ARGument ABLEの短縮形から派生した用語、別名SARGableがあります。クエリの条件(または述語)は、DBMSエンジンがインデックスを利用してクエリの実行を高速化できる場合、SARGableであると言われます。その一方で、SARGableではないクエリは、非SARGableクエリと呼ばれます。この効果は、インデックスで識別された特定のページのリストにジャンプする代わりに、インデックスのない本で毎回1ページ目から特定の用語を検索するのと似ています。明らかに、これはクエリ時間に悪影響を与えます。そのため、クエリ最適化の手順の1つは、そのような条件をSARGableに変換することです。

上記のような条件をSARGableなものにするためには、インデックス付きの列で関数を使用しないようにする必要があります。これを行うためには、Like演算子を使用して、この論理的に同等の(およびSARGableな)クエリでリクエストを表現する必要があります。

like_query (54K)

実行時間が大幅に改善されていることに注目してください。

結論

よくあるSQLクエリの間違いに関するこの2回目の記事では、非SARGableなクエリ条件が、データベースエンジンに強制的にテーブルの全ての行を評価させることにより、クエリのパフォーマンスをどのように低下させるかを学びました。その解決策は、関数呼び出しに依存しない論理的に同等の(およびSARGableな)条件でリクエストを表現することです。

Navicat 16 for MySQLを試したい場合は、こちらから14日間のトライアル版をダウンロードできます。

ブログのアーカイブ
シェア