標準のBツリーインデックスでProjects
呼び出される列で呼び出されるテーブルがあるとします。Budget
このテーブルには50,000のプロジェクトがあり、そのうちの1%だけが100万を超える予算を持っています。SQLクエリを実行した場合:
SELECT * From Projects WHERE Budget > 1000000;
プランナーは、インデックス範囲スキャンを使用Budget
して、ヒープテーブルから行を取得します。ただし、クエリを使用する場合:
SELECT * From Projects WHERE Budget > 50;
プランナーは、このクエリがいずれにせよほとんどまたはすべての行を返すことになり、インデックスのすべてのページをメモリにロードする理由がないことを知っているため、テーブルに対して順次スキャンを実行する可能性があります。
ここで、クエリを実行するとします。
SELECT * From Projects WHERE Budget > :budget;
:budget
データベースに渡されるバインドパラメータはどこにありますか。私が読んだものから、上記のクエリはキャッシュされ、カーディナリティに関するデータは推測できません。実際、ほとんどのデータベースは均等な分散を想定しており、キャッシュされたクエリプランはそれを反映します。これは私を驚かせました。通常、バインドパラメータの利点について読むと、SQLインジェクション攻撃を防ぐことができます。
明らかに、新しいプランをコンパイルする必要がないため、結果のクエリプランが同じである場合、これによりパフォーマンスが向上する可能性がありますが、の値が大幅に異なる場合はパフォーマンスが低下する可能性もあります。:budget
私の質問:クエリプランが生成されてキャッシュされる前にバインドパラメータが解決されないのはなぜですか?最新のデータベースは、クエリの最適な計画を生成するように努めるべきではありません。つまり、各パラメーターの値を調べて、正確なインデックス統計を取得する必要がありますか?
注: mySqlはSQLプランをキャッシュしないため、この質問はおそらくmySqlには当てはまりません。ただし、Postgres、Oracle、およびMSSQLでこれが当てはまる理由に興味があります。