2017-10-09 9 views
1

を選択し、次の例で考えてみましょう:このクエリは、ROWID列なしで表を作成し、値を挿入(X、x)をクエリプランナを助けるために 1000年< X < 2000が実行することができますどこSQLiteは間違ったクエリプラン

DROP TABLE IF EXISTS t1; 
CREATE TABLE t1(a INTEGER PRIMARY KEY, b) WITHOUT ROWID; 
WITH RECURSIVE 
    cnt(x) AS (VALUES(1000) UNION ALL SELECT x+1 FROM cnt WHERE x<2000) 
INSERT INTO t1(a,b) SELECT x, x FROM cnt; 
CREATE INDEX t1b ON t1(b); 

を分析する。

ANALYZE; 

EXPLAIN QUERY PLAN 
SELECT * FROM t1 WHERE b BETWEEN 500 AND 2500; 

EXPLAIN QUERY PLAN 
SELECT * FROM t1 WHERE b BETWEEN 2900 AND 3000; 

いずれの場合も、出力は次のようになります。しかし、とにかく私たちはテーブル全体を反復処理する必要がある理由(最初のクエリのための)インデックスを使用しても意味がない0|0|0|SEARCH TABLE t1 USING COVERING INDEX t1b (b>? AND b<?) ので、通常のSCAN TABLEはいるようですより効率的です。まさにこの方法でROWID仕事を持つテーブルに:

DROP TABLE IF EXISTS t1; 
CREATE TABLE t1(a, b); 
WITH RECURSIVE 
    cnt(x) AS (VALUES(1000) UNION ALL SELECT x+1 FROM cnt WHERE x<2000) 
INSERT INTO t1(a,b) SELECT x, x FROM cnt; 
CREATE INDEX t1a ON t1(a); 
ANALYZE; 

EXPLAIN QUERY PLAN 
SELECT * FROM t1 WHERE a BETWEEN 500 AND 2500; 

EXPLAIN QUERY PLAN 
SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000; 

この場合、出力は次のようになります。0|0|0|SCAN TABLE t1 0|0|0|SEARCH TABLE t1 USING INDEX t1a (a>? AND a<?)

ので、誰でも問い合わせプランナがROWIDテーブルなしのクエリを最適化する方法を説明できますか?

+1

私は本当に何人かの人々がこのような素敵な質問にDV理由を理解しません。彼らはその質問を読んだり理解したりするのでしょうか?私は釣り合いを取るためにupvoted;) –

答えて

2

いずれの場合も、出力は次のようになります(??B>とB <) 0 | 0 | | 0 INDEXのT1Bを覆って使用して、検索テーブルT1

しかし、インデックスを使用しても意味は(ありません の最初のクエリ)なぜなら、私たちは 全体のテーブルを反復する必要があるため、通常のSCAN TABLEはより効率的であるようです。 - 全くのテーブルにアクセスしていない、それは索引のみ使用されることを意味:

あなたが カバーINDEX一部を逃しました。

すべての行が必要な場合は、通常の索引アクセス(「COVERING」なし)が全表スキャンよりも遅くなる可能性がありますが、これは索引専用スキャンの場合には当てはまりません。

インデックス、ここでしかスキャンについてもっと読む:ROWIDなしhttp://use-the-index-luke.com/sql/clustering/index-only-scan-covering-index

EDIT

クラスタ化インデックス、他のデータベースでいわゆるれているものSQLiteのである:彼らはすべて表の列が含まれています。したがって、すべての列を選択した場合でも(select *など)、テーブルにアクセスする必要はありません。

ここにクラスタ化インデックスについて詳しく読む:http://use-the-index-luke.com/sql/clustering/index-organized-clustered-index

+0

待って、なぜ2番目の場合(私たちはROWID列でテーブルを使用する)それは検索が通常のインデックスを使用していると言われる?インデックスt1aを使用してROWIDを検索した後、RIDIDを使用して 'a'を検索することをお勧めします。文字通りカバレッジ指標ではありません。私は正しい? – NikitaRock

+0

@NikitaRockは私の答えにコメントを追加しました。 –

+0

したがって、ROWIDのないテーブルでクエリを最適化するためにanalyzeを実行する意味はありませんか? – NikitaRock

関連する問題