我有两张桌子:
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");
每个表包含大约50万条记录,实际上,每个类型大约有20个,TEXT类型(在上面发布的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个SEQ SCAN,而不是查找索引。这是预期的行为吗?
答案 0 :(得分:4)
由于您没有WHERE
条件,因此您可以有效地阅读整个表格。运行顺序扫描并且根本不涉及任何索引会更便宜。
尝试:
EXPLAIN
SELECT s.sample_id, s.project_id, s.technician_id, a.mo_ppm
FROM soils s
JOIN assays a USING (sample_id)
WHERE <some condition that returns few rows>;
...应该使用与WHERE
条件匹配的索引。
您无需在PRIMARY KEY
列上定义索引。 PK约束自动使用唯一索引实现。您的附加索引是多余的,没有用处。
外键列上的索引是个好主意,但是在您的示例中没有一个看起来很奇怪。就像这两个表可以组合成一个。可能只是对测试用例的过度简化。
最后,对于大表,我会考虑使用简单的integer
主键而不是text
,可能是serial
列。这通常更快。
答案 1 :(得分:1)
是的,这是预期的行为。另一方面,它取决于您的random_page_cost
,seq_page_cost
和effective_cache_size
设置。您的查询没有WHERE
子句,因此按顺序读取所有内容可能会更快。您可以尝试惩罚顺序扫描:
set enable_seqscan = off;
explain analyse <your query>;
然后比较计划/成本/ IO等待(不可能禁用seq-scan但成本非常高 - ~1e7(或1e8))。
如果查询中有SSD和WHERE
子句,则可以降低random_page_cost to 1.5..2.5并鼓励PG使用索引。