1

코드를 작성한 이후로 오랜 시간이 걸렸습니다. 이전에는 SQLite를 사용하지 않았지만 다 대다 관계는 너무 근본적 이었지만, 빨리 사용하는 방법이 있어야했습니다. ...SQLite가 다 대다 관계 테이블의 쿼리에 인덱스를 사용하지 않는 이유는 무엇입니까?

This (데이터를 읽기 전용으로되어 있기 때문에 합리적인 것보다 더 많은,하지만 문제) 난 그냥 확인하기 위해, 내가 생각할 수있는 모든 인덱스에 넣어 가지고

CREATE TABLE a (_id INTEGER PRIMARY KEY, a1 TEXT NOT NULL); 
CREATE TABLE b (_id INTEGER PRIMARY KEY, fk INTEGER NOT NULL REFERENCES a(_id)); 
CREATE TABLE d (_id INTEGER PRIMARY KEY, d1 TEXT NOT NULL); 
CREATE TABLE c (_id INTEGER PRIMARY KEY, fk INTEGER NOT NULL REFERENCES d(_id)); 
CREATE TABLE b2c (fk_b NOT NULL REFERENCES b(_id), fk_c NOT NULL REFERENCES c(_id), CONSTRAINT PK_b2c_desc PRIMARY KEY (fk_b, fk_c DESC), CONSTRAINT PK_b2c_asc UNIQUE (fk_b, fk_c ASC)); 
CREATE INDEX a_a1 on a(a1); 
CREATE INDEX a_id_and_a1 on a(_id, a1); 
CREATE INDEX b_fk on b(fk); 
CREATE INDEX b_id_and_fk on b(_id, fk); 
CREATE INDEX c_id_and_fk on c(_id, fk); 
CREATE INDEX c_fk on c(fk); 
CREATE INDEX d_id_and_d1 on d(_id, d1); 
CREATE INDEX d_d1 on d(d1); 

하십시오 추상화 내 데이터베이스의 버전입니다. 그럼에도 불구하고이 쿼리

SELECT count(*) 
FROM a, b, b2c, c, d 
WHERE a.a1 = "A" 
    AND a._id = b.fk 
    AND b._id = b2c.fk_b 
    AND c._id = b2c.fk_c 
    AND d._id = c.fk 
    AND d.d1 ="D"; 

에 관계 테이블 B2C는 인덱스를 사용하지 않습니다

0|0|2|SCAN TABLE b2c 
0|1|1|SEARCH TABLE b USING INTEGER PRIMARY KEY (rowid=?) 
0|2|0|SEARCH TABLE a USING INTEGER PRIMARY KEY (rowid=?) 
0|3|3|SEARCH TABLE c USING INTEGER PRIMARY KEY (rowid=?) 
0|4|4|SEARCH TABLE d USING INTEGER PRIMARY KEY (rowid=?) 

쿼리를 사용할 수있을 천천히 약 2 배이다. SQLite가 b2c에 인덱스를 사용하도록하는 방법이 있습니까?

감사합니다.

답변

0

중첩 루프 조인에서 가장 바깥 쪽 테이블은 데이터베이스가 모든 행을 처리하기 때문에 인덱스를 조인에 사용하지 않습니다.

조인에 인덱스를 사용하려면 인덱스와 다른 열이 같아야합니다. affinity이 있어야합니다. 일반적으로 두 열 모두 동일한 유형이어야 함을 의미합니다.

b2c 열의 유형을 INTEGER로 변경하십시오. 가장 바깥 쪽 테이블이 적합 할 수 있습니다, 다음 필터 인덱스를 사용할 수 있도록하는 것처럼 a 또는 d를 사용하여

a1 또는 d1에 조회가 매우 선택적 경우

. ANALYZE을 실행 해보십시오.

도움이되지 않는 경우 CROSS JOIN 또는 INDEXED BY과 강제로 가입 할 수 있습니다.

+0

감사합니다. 실제 데이터베이스에서 ANALYZE를 실행했습니다. 그러나 릴레이션 테이블은 여전히 ​​인덱스를 사용하지 않습니다. 쿼리 계획 설명의 두 번째 줄에 있습니다 (이것은 가장 바깥 쪽 루프가 아니라고 가정합니다). 첫 번째 행은 색인의 사용법을 보여줍니다. –

+0

좋아, 나는 그것을 시도했다. 그리고 그 결과는 신비 스럽습니다 ... CROSS JOIN을 사용하면 루프의 위치는 바꿀 수 있지만 인덱스는 사용할 수 없습니다. INDEXED BY를 사용했을 때 SQLITE의 동작이 다양 함 : "PK_b2c_desc"에 대해 SQLite가 "해당 인덱스가 없습니다"를 반환했습니다. "giberish"및 "b_id_and_fk"와 동일합니다. "sqlite_autoindex_b2c_1"에 대한 SQLITE는 "쿼리 솔루션 없음"을 반환했습니다. SQLite는 테이블 b2c에 대한 create table 문에서 인덱스 명령을 무시하고 자체 인덱스 sqlite_autoindex_b2c_1을 만들었습니다. 하지만 어떻게 든 그것을 사용할 수 없습니까? –

+0

업데이트 됨; 필자는'b2c'에서 누락 된 유형을 간과했습니다. –