0

我有两张桌子:

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,而不是查找索引。这是预期的行为吗?

4

2 回答 2

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列。这通常更快。

于 2012-12-13T08:11:38.220 回答
1

是的,这是预期的行为。另一方面,它取决于您的random_page_cost,seq_page_costeffective_cache_size设置。您的查询没有WHERE子句,因此按顺序读取所有内容可能会更快。您可以尝试惩罚顺序扫描:

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

然后比较计划/成本/IO等待(无法禁用seq-scan,但成本非常高——~1e7(或1e8))。

如果您WHERE的查询中有 SSD 和子句,那么您可以将 random_page_cost 降低到 1.5..2.5并鼓励 PG 使用索引。

于 2012-12-13T22:57:55.870 回答