いつテーブルでインデックスを使用する必要がありますか?
編集:今はfirebird 2.5で作業していますが、ほとんどの場合、SQL Server 2005/2008を使用しています。
一般的に、私のインデックス作成戦略は次のようなものです(私は今のところSQL Serverを排他的に使用しています-必要に応じて独自のデータベースシステムに適応してください)。
goodクラスタリングキーを選択-GUIDではなく、VARCHAR(250)
などではない-goodクラスタリングキーは狭く、ユニークで、安定していて、増え続ける-INT IDENTITY
のようなものが完璧です。これをクラスター化された主キーにします->テーブルの最初のインデックスを提供します
別のテーブルへの外部キーとして使用されている列の場合-インデックスを追加します。これは、単一列のインデックスにすることも、複合インデックスにすることもできます。外部キー列がそのインデックスのfirst列であることが重要です(複合インデックスを使用している場合)-それ以外の場合は、JOIN
の参照の整合性のチェックまたは参照整合性のチェックの利点が得られますシステムで利用できない
そして、それは今のところ以上です。
次に、システムを実行します-観察し、測定します-ベースラインを確立します。アプリは十分高速ですか?はいの場合->完了です-家に帰って空き時間を楽しんでください。
そうでない場合:アプリが十分に高速でない理由に関するデータと指標の収集を開始します。見てください。 SQL ServerのDMVのように、クエリのパフォーマンスが最も悪いことを通知するもの、または欠落インデックスDMVです。それらを分析します。あなたが改善できるものを見てください。 一度に1つのインデックスを追加します:観察、測定、ベースラインと比較します。
改善がある場合->そのインデックスをそのままにして、この測定値が新しいベースラインになります。あなた(とあなたのユーザー)がアプリのパフォーマンスに満足するまで(そして、そして家に帰ってあなたの休暇を楽しんでください)洗い流して繰り返します。
SQL Serverでのオーバーインデックスは、インデックスがない場合よりも悪いになる可能性があります。初めはあまりにも多くのインデックスで始めないでください! goodクラスター化PKと外部キーの非クラスター化インデックスのみを確立します-それだけです-次に、そのサイクルを観察、測定、最適化、および繰り返します。
これは非常に複雑な議論です。覚えておくべきことがいくつかあります。主に、テーブルにある行数ではなく、それに対して実行するクエリに基づいてインデックスを検討する必要があります。インデックスはクエリの選択のみに役立ちます。同時に、テーブルの行を変更するだけでなく、インデックスを変更する必要があるため、挿入、削除、更新のパフォーマンスがわずかに低下します。
あなたはこの問題に慣れていないようです。私が提案するのは、実行計画を見て、すべての「スキャン」操作を排除しようとすることです。シークがあるように常に見る必要がありますが、それでも、テーブルにあるインデックスの量とバランスを取る必要があります。
SQL Serverを使用している場合は、SQL Serverプロファイラーを使用してトレースを実行すると、
編集:
そのような場合、非インデックスの選択/読み取りは、インデックスの読み取りよりも効果的ですか?
はい。ただし、このケースが発生した場合、エンジンはインデックスを使用しないほどスマートになります
インデックスは、テーブルから行の一部を選択するのに適しています。主キー値によるクエリは、インデックスの最適な利用方法です。最悪のシナリオは、インデックスページおよび参照データページを読み取る必要があるため、インデックスを介してテーブルからすべての行にアクセスすることです。別の例は、結果セットのメモリ内ソートは、ソートされた列のインデックスを介して結果セットをソートするよりも高速である可能性があることです。そして、忘れないでください。インデックスはクエリのパフォーマンスを向上させる可能性がありますが、インデックスは書き込みパフォーマンスを低下させます。
ベースラインをとり、パフォーマンスを測定するためにある種のトレースユーティリティを使用することなどについて言及した人もいます。確立されたパフォーマンスで問題がなければ、次に進んでください。そうでない場合は、実行プラン、物理データモデル(利用可能なインデックス)を分析し、統計を再計算して、オプティマイザがより適切な実行プランを選択するのに役立つかどうかを確認します。 DBMSが利用可能なRAMを利用できる(許可されている)ことを確認してください。ディスクI/Oなどを最小限に抑えるようにしてください。
Firebird 2.5の場合、新しく追加されたFirebird Trace APIは天の恵みです。これで、パフォーマンスカウンター(実行計画、実行時間、I/O統計など)を使用して、データベースに対して何が実行されたかをほぼリアルタイムで追跡できるようになりました。そして、サードパーティ製品 FB TraceManagerpscene Productions と呼ばれているため、Trace APIを使用する喜びが生まれます。
このクエリを使用して、どのテーブルにインデックスが必要であるかを知る手掛かりを取得します。
-- Missing Indexes for current database by Index Advantage (Query 57) (Missing Indexes)
SELECT DISTINCT CONVERT(decimal(18,2), user_seeks * avg_total_user_cost * (avg_user_impact * 0.01)) AS [index_advantage],
migs.last_user_seek, mid.[statement] AS [Database.Schema.Table],
mid.equality_columns, mid.inequality_columns, mid.included_columns,
migs.unique_compiles, migs.user_seeks, migs.avg_total_user_cost, migs.avg_user_impact,
OBJECT_NAME(mid.[object_id]) AS [Table Name], p.rows AS [Table Rows]
FROM sys.dm_db_missing_index_group_stats AS migs WITH (NOLOCK)
INNER JOIN sys.dm_db_missing_index_groups AS mig WITH (NOLOCK)
ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details AS mid WITH (NOLOCK)
ON mig.index_handle = mid.index_handle
INNER JOIN sys.partitions AS p WITH (NOLOCK)
ON p.[object_id] = mid.[object_id]
WHERE mid.database_id = DB_ID()
ORDER BY index_advantage DESC OPTION (RECOMPILE);
これは北を与えるだけであることに注意してください、あなたはまだ上で答えられたことを考慮に入れる必要があります。
質問の2番目の部分に関して、テーブルに15行しかない場合、テーブルが非常に小さいため、テーブルのインデックスがいくつあっても常にスキャンされる可能性が高くなります。