2016-07-14 12 views
0

速く走る(Slow Indexes Part II計画は、私はマルクスWinandのウェブサイトからのコード例を再現しようとしています

テストケース:

  1. が分析されていないテーブルを作成し、インデックスを紹介します フルテーブルスキャンよりも動作が遅くなります。
  2. そのインデックスでクエリを分析します。
  3. インデックススキャンをオフにします。
  4. このクエリを再度分析します。

私はこのテストを行なったし、データベースが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" 
+1

条件「subsidiary_id = 1」は、テーブル内のすべての行の50%を選択します。その多くの行では、通常Seqスキャンを使用するとインデックス検索が高速になります。 2回目の実行で 'enable_bitmapscan'をオンにしたかどうかはわかりません。正確なPostgresのバージョン( 'select version()') –

+0

実際に 'subsidiary_id = 1'は全行の29%を選択します。 'enable_bitmapscan'はfalseです。私は、これらの文を1つのトランザクションで実行していると思います。私はそれがより速くなるとも考えましたが、実際のスキャンの計画では反対です。インデックススキャンの時間はほぼ2倍かかります。 – Skoffer

+0

PostgreSQL 9.5.2、Visual C++ビルド1800,64ビット – Skoffer

答えて

0

プランナーは、データの局所性を計算していない - それはディスクから読み取るたびに期待しています。デフォルトでは、ファイルシステムキャッシュ用に十分なRAMがあるか、またはIOが使用されていない場合は、より高速なクエリを見つけることができます。しかし、PostgreSQLプランナーは、ディスクとキャッシュを利用するように構成されており、実際に動作しています。おそらくあなたは無負荷でサーバー上でテストを行ったでしょう。サーバー上でより現実的な負荷をシミュレートし、テストを繰り返してみてください。

+0

ありがとう、それは良い点です。 – Skoffer

関連する問題