빠르게 실행 (Slow Indexes Part II)계획은 내가 마르쿠스 Winand 웹 사이트에서 코드 예제를 재현하려고
테스트 케이스 :
- 분석되지 않은 테이블을 만들고 인덱스를 소개합니다 전체 테이블 스캔보다 느리게 작동합니다.
- 해당 색인이있는 검색어를 분석하십시오.
- 색인 스캔을 끕니다.
- 이 쿼리를 다시 분석하십시오.
이 테스트를 수행했으며 데이터베이스는 INDEX SCAN에서 SEQ SCAN으로 전환 중입니다.
그러나 실제 숫자를 살펴보면 SEQ SCAN 쿼리는 실제로 인덱스 INDEX 쿼리보다 느립니다.
planner가 비용이 많이 들고 느리더라도 SEQ SCAN 쿼리로 전환하는 이유는 무엇입니까? 여기
내 결과입니다 :drop table if exists employees;
CREATE TABLE employees (
employee_id bigint NOT NULL,
subsidiary_id bigint not null,
first_name text NOT NULL,
last_name text NOT NULL,
date_of_birth DATE NOT NULL,
phone_number text NOT NULL,
CONSTRAINT employees_pk PRIMARY KEY (subsidiary_id, employee_id)
);
SELECT setseed(0.5);
insert into employees
select a, 1, random()::text,random()::text, now(), '123123123'
from generate_series(1,200000) as t(a)
union all
select a, 2, random()::text,random()::text, now(), '123123123'
from generate_series(1,500000) as t(a);
set enable_bitmapscan to false;
explain analyze
select *
from employees
where subsidiary_id = 1 and first_name = '0.550025727134198';
"QUERY PLAN"
"Index Scan using employees_pk on employees (cost=0.42..8596.82 rows=12 width=116) (actual time=0.024..38.409 rows=1 loops=1)"
" Index Cond: (subsidiary_id = 1)"
" Filter: (first_name = '0.550025727134198'::text)"
" Rows Removed by Filter: 199999"
"Planning time: 0.114 ms"
"Execution time: 38.429 ms"
analyze employees;
explain analyze
select *
from employees
where subsidiary_id = 1 and first_name = '0.550025727134198';
"QUERY PLAN"
"Seq Scan on employees (cost=0.00..19142.00 rows=1 width=66) (actual time=0.017..66.579 rows=1 loops=1)"
" Filter: ((subsidiary_id = 1) AND (first_name = '0.550025727134198'::text))"
" Rows Removed by Filter: 699999"
"Planning time: 0.431 ms"
"Execution time: 66.601 ms"
set enable_seqscan to false;
explain analyze
select *
from employees
where subsidiary_id = 1 and first_name = '0.550025727134198';
"QUERY PLAN"
"Index Scan using employees_pk on employees (cost=0.42..23697.20 rows=1 width=66) (actual time=0.041..36.159 rows=1 loops=1)"
" Index Cond: (subsidiary_id = 1)"
" Filter: (first_name = '0.550025727134198'::text)"
" Rows Removed by Filter: 199999"
"Planning time: 0.061 ms"
"Execution time: 36.178 ms"
조건 'subsidiary_id = 1'은 테이블의 모든 행 중 50 %를 선택합니다. 그 많은 행의 경우 Seq 스캔을 사용하면 일반적으로 색인 조회가 빠릅니다. 두 번째 실행을 위해 enable_bitmapscan을 켰는 지 여부는 분명하지 않습니다. 정확한 Postgres 버전은 무엇입니까 ('select version()') –
사실'subsidiary_id = 1'은 모든 행의 29 %를 선택합니다. 'enable_bitmapscan'은 false입니다. 하나의 트랜잭션에서이 명령문을 실행하고 있습니다. 나는 또한 그것이 더 빠를 것이라고 생각했으나 seq 스캔을위한 실제 계획은 그 반대라고 말한다. 인덱스 스캔 시간이 거의 두 번 걸립니다. – Skoffer
Visual C++ 빌드 1800, 64 비트에서 컴파일 된 PostgreSQL 9.5.2, – Skoffer