2

約500K行を含むテーブルがあります。テーブルには、「ステータス」列にインデックスがあります。したがって、次のExplainコマンドを実行します。

EXPLAIN QUERY PLAN SELECT * FROM my_table WHERE status = 'ACTIVE'

予測可能な「説明」になります。

SEARCH TABLE my_table USING INDEX IDX_my_table_status (status=?) (~10 rows)

テーブルに多くの行が追加された後、「ANALYZE」と呼びます。その後、クエリが非常に遅くなったように見えたので、explainを再実行すると、次のようになります。

SCAN TABLE my_table (~6033 rows)

私が最初に気付くのは、行の見積もりが両方ともかなりずれていることです。最大の懸念は、ANALYZEを実行するとインデックスがスキップされるように見えるという事実です。私はREINDEXを試しました-無駄に。インデックスを元に戻す唯一の方法は、インデックスを削除してから再作成することです。誰かがこれを見たことがありますか?これはバグですか?私が間違っていることについて何か考えはありますか?複数のデータベースでこれを試しましたが、同じ結果が得られました。これは私のPC、MAC、iPhone/iPadにあります-すべて同じ結果です。

4

2 に答える 2

1

SQLiteがインデックスを使用してテーブルから行をフェッチする場合、最初にインデックスページを読み取り、次に1つ以上の一致するレコードを含むすべてのテーブルのページを読み取る必要があります。一致するレコードが多数ある場合、ほとんどすべてのテーブルのページに1つが含まれている可能性が高いため、インデックスを調べるには、さらに多くのページを読み取る必要があります。

ただし、SQLiteのクエリプランナーにはインデックスまたはテーブルのレコードサイズに関する情報がないため、推定値がずれている可能性があります。

によって収集された情報は、および多分テーブルANALYZEに保存されます。あなたのテーブルに関する情報が何であるかを示してください。 その情報がデータの実際の分布を反映していない場合は、再実行を試みるか、テーブルからその情報を削除することができます。sqlite_stat1sqlite_stat3
ANALYZEsqlite_stat*

インデックス付きフィールドで使用する場合は、インデックスを強制的に通過させることができORDER BYます。(INDEXED BYドキュメントに記載されているように、クエリのパフォーマンスの調整に使用することを目的としたものではありません。)

テーブルのすべてのフィールドを選択する必要がない場合は、それらのクエリのフィールドにインデックスを作成して、カバーするインデックスを作成することで、特定のクエリを高速化できます。

于 2012-10-18T06:43:11.187 に答える
0

クエリ実行プランでは、「ステータス」のようなカーディナリティの低い列に既存のインデックスを使用しないようにすることは珍しくありません。この列には、おそらくいくつかの異なる値しかありません。多くの場合、dbテーブルをスキャンすることでルックアップを実行する方が高速です。(一部のDBAは、カーディナリティの低い列にインデックスを付けないことを推奨しています。)

ただし、Explainプランの大幅に変化する行数に基づいて、SQLiteの「analyze」はInnoDBストレージエンジンを使用する場合のMySQLの「analyze」と同様に機能すると推測しています。MySQLの「analyze」はテーブルデータにランダムなダイブセットを実行して、行数、インデックスカーディナリティなどを決定します。ランダムなダイブのため、「analyze」が実行されるたびに統計が変化し、クエリ実行プランが異なる場合があります。カーディナリティの低い列は、誤った統計の影響をさらに受けやすくなります。たとえば、ランダムダイブは、テーブル内の行の大部分が「アクティブ」ステータスであることを示している可能性があるため、インデックスを使用するよりもテーブルスキャンを効率的に行うことができます。 。(私はSQLiteの専門家ではないので、「分析」についての私の予感があれば誰かがチャイムを鳴らしてください

「indexedby」(http://www.sqlite.org/lang_indexedby.htmlを参照)を使用して、クエリでのインデックスの使用をテストできますが、通常、インデックスの使用を強制することは最後の手段です。RDBMSが異なれば、パーティショニングやビットマップインデックスの使用など、カーディナリティの低い問題に対するソリューションも異なります。カーディナリティの低い列のクエリ/インデックス作成に対するSQLite固有のソリューションを調査することをお勧めします。

于 2012-10-18T05:28:27.273 に答える