Postgres主键“小于”操作很慢

时间:2017-01-04 17:51:21

标签: performance postgresql indexing

考虑下表

CREATE TABLE COMPANY(
   ID BIGINT PRIMARY KEY     NOT NULL,
   NAME           TEXT    NOT NULL,
   AGE            INT     NOT NULL,
   ADDRESS        CHAR(50),
   SALARY         REAL
);

如果我们在此表中有1亿个随机数据。

Select age from company where id=2855265

在不到一毫秒的时间内执行

Select age from company where id<353

返回少于50行并在不到一毫秒的时间内执行

两个查询都使用索引

但是以下查询使用全表扫描并在3秒内执行

Select age from company where id<2855265

返回少于500行

如何加快选择主键小于变量的查询?

2 个答案:

答案 0 :(得分:1)

性能

谓词id < 2855265可能会返回表中的大部分行。除非Postgres在表统计信息中只有大约500行的信息,否则它可能会从索引扫描切换到位图索引扫描,甚至是顺序扫描。说明:

我们需要查看EXPLAIN (ANALYZE, BUFFERS)的输出以供查询。

当您重复查询时,您会获得相同的效果吗?可能存在缓存效果。

无论哪种方式,3秒是慢慢 500行的方式,Postgres可能正在使用过时或不精确的表统计信息。或者您的服务器配置可能存在问题(资源不足)。或者还有其他一些不太常见的原因,包括硬件问题......

如果VACUUM ANALYZE没有帮助,VACUUM FULL ANALYZE可能会有帮助。它有效地重写整个表和所有索引在原始状态。对表进行独占锁定,可能与并发访问冲突!

我还会考虑增加id列的统计目标。说明:

表定义?

无论你做什么,你的表定义似乎都存在各种问题:

CREATE TABLE COMPANY(
   ID BIGINT PRIMARY KEY NOT NULL,  -- int is probably enough. "id" is a terrible column name
   NAME      TEXT    NOT NULL,  -- "name" is a teriible column name
   AGE       INT     NOT NULL,  -- typically bad idea to store age, store birthday instead
   ADDRESS   CHAR(50),   -- never use char(n)!
   SALARY    REAL        -- why would a company have a salary? never store money as real
);

你可能想要这样的东西:

CREATE TABLE emmployee(
   emploee_id    serial PRIMARY KEY
   company_id    int NOT NULL  -- REFERENCES company(company_id)?
 , birthday      date NOT NULL
 , employee_name text NOT NULL
 , address       varchar(50)   -- or just text
 , salary        int           -- store amount as *Cents*
);

相关:

答案 1 :(得分:0)

您需要执行VACUUM ANALYZE company;来更新计划。