2017-10-09 6 views
1

예를 들어 다음을 고려 잘못된 쿼리 계획을 선택합니다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); 

이 쿼리는 ROWID 컬럼없이 테이블을 생성하고 값을 삽입 (X를, X) 여기서 쿼리 계획을 돕기 위해 1000 < X < 2000은 실행을 할 수 있습니다 분석.

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 테이블에 보인다 더 효율적으로 정확히 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

두 경우의 출력은 : 0 | 0 | 0 | SEARCH T1 테이블 인덱스 T1b의 취재 사용하지만

, 인덱스 (사용하는 것은 의미가 없다 (b> AND B <는?) 어쨌든 우리가 전체 테이블을 반복해야하는 이유 첫 번째 쿼리)에 대한, 그래서 일반 SCAN 표는보다 효율적인 것 같다. - 모든 테이블에 액세스되지는 인덱스 만 사용하고 의미

당신은 덮고 INDEX 부분을 놓쳤다.

당신은 ("COVERING"이없는) 일반 인덱스 액세스는 모든 행이 필요한 경우 전체 테이블 스캔보다 느릴 수 있음을 잘하지만, 이것은 인덱스 전용 스캔의 경우에는 해당되지 않습니다. 인덱스 전용 여기 스캔에 대해

더 읽기 : http://use-the-index-luke.com/sql/clustering/index-only-scan-covering-index

편집

ROWID없이 클러스터 인덱스 다른 데이터베이스에서 소위 무엇 SQLite는에있다 : 그들은 모든 테이블 열을 포함 . 따라서 모든 열 (예 : select *)을 선택하더라도 테이블을 방문 할 필요가 없습니다.

여기에 클러스터 된 인덱스에 대한 자세한 내용을 읽어 http://use-the-index-luke.com/sql/clustering/index-organized-clustered-index

+0

기다립니다,하지만 왜 두 번째 경우 (우리가 ROWID 열이있는 테이블을 사용하는 경우)에는 검색 일반 인덱스를 사용했다고한다? 내 제안은 rowid를 사용하여 색인 t1a를 사용하여 검색 한 후 'a'가 rowid를 사용하여 검색한다는 것입니다. 따라서 문자 그대로 그것은 커버리지 인덱스가 아닙니다. 내가 맞습니까? – NikitaRock

+0

@NikitaRock이 내 답변에 덧글을 추가했습니다. –

+0

그래서 rowid가없는 테이블에서 쿼리를 최적화하기 위해 analyze를 실행하는 것은 의미가 없습니까? – NikitaRock