2012-12-13 23 views
0

我有兩個表:這個PostgreSQL查詢應該使用索引嗎?

CREATE TABLE soils (
    sample_id  TEXT PRIMARY KEY, 
    project_id  TEXT, 
    technician_id TEXT 
); 
CREATE INDEX soils_idx 
ON soils 
USING btree 
(sample_id COLLATE pg_catalog."default"); 

CREATE TABLE assays (
    sample_id TEXT PRIMARY KEY, 
    mo_ppm  NUMERIC 
    ); 
CREATE INDEX assays_idx 
ON assays 
USING btree 
(sample_id COLLATE pg_catalog."default"); 

每個表包含大約一個半萬條記錄,而在現實中,每約20個額外的列式的文字,(在DDL省略上面貼在這裏節省時間)。

當我執行查詢:

EXPLAIN SELECT 
    s.sample_id, s.project_id, s.technician_id, a.mo_ppm 
FROM 
    soils AS s INNER JOIN assays AS a ON s.sample_id = a.sample_id 

我得到2次序列掃描,而不是查找到索引中。那是預期的行爲?

回答

4

由於您沒有WHERE條件,所以您可以有效地讀取整個表格。運行順序掃描並跳過索引查找可能會更便宜。

嘗試:

EXPLAIN SELECT 
    s.sample_id, s.project_id, s.technician_id, a.mo_ppm 
FROM 
    soils As s INNER JOIN assays As a ON s.sample_id = a.sample_id 
WHERE <some condition that returns a few rows>; 

..和至少一個索引應當使用(取決於WHERE條件)。您不需要在PRIMARY KEY列上定義索引。 PK約束是通過自動創建唯一索引來實現的。您的額外索引是多餘的,無用的。

外鍵列上的索引將是一個好主意,但在您的示例中沒有,這看起來很奇怪。就像兩張桌子可以合併成一個一樣。測試用例可能只是過度簡化。

最後,對於大表,我會考慮使用簡單的integer主鍵而不是text,可能是serial列。由於多種原因,這通常會快一點。

1

是的,這是預期的行爲。另一方面則取決於您的random_page_cost,seq_page_costeffective_cache_size設置。您的查詢沒有WHERE子句,因此按順序讀取所有內容可能會更快。你可以嘗試懲罰順序掃描:

set enable_seqscan = off; 
explain analyse <your query>; 

,然後比較計劃/成本/ IO等待(這是不可能禁用序列掃描,但它得到非常高的成本 - 〜1E7(或1E8))。

如果在查詢中有SSD和WHERE子句,則可以降低random_page_cost to 1.5..2.5並鼓勵PG使用索引。

相關問題