速く走る(Slow Indexes Part II)計画は、私はマルクスWinandのウェブサイトからのコード例を再現しようとしています
テストケース:
- が分析されていないテーブルを作成し、インデックスを紹介します フルテーブルスキャンよりも動作が遅くなります。
- そのインデックスでクエリを分析します。
- インデックススキャンをオフにします。
- このクエリを再度分析します。
私はこのテストを行なったし、データベースがSEQ SCANにインデックススキャンを切り替えています。
実際の数字を見ると、SEQ SCANクエリは実際にインデックスINDEXクエリよりも遅くなります。
コストが高く、実行が遅い場合でも、プランナーが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スキャンを使用するとインデックス検索が高速になります。 2回目の実行で 'enable_bitmapscan'をオンにしたかどうかはわかりません。正確なPostgresのバージョン( 'select version()') –
実際に 'subsidiary_id = 1'は全行の29%を選択します。 'enable_bitmapscan'はfalseです。私は、これらの文を1つのトランザクションで実行していると思います。私はそれがより速くなるとも考えましたが、実際のスキャンの計画では反対です。インデックススキャンの時間はほぼ2倍かかります。 – Skoffer
PostgreSQL 9.5.2、Visual C++ビルド1800,64ビット – Skoffer