考虑下表
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 行
如何加快选择主键小于变量的查询?
最佳答案
性能
谓词id < 2855265
可能会返回表中的大部分行。除非 Postgres 的表统计信息预计只有大约 500 行,否则它可能会从索引扫描切换到位图索引扫描,甚至是顺序扫描强>.说明:
我们需要查看 EXPLAIN (ANALYZE, BUFFERS)
的输出为您的查询。
当您重复查询时,是否获得相同的性能?可能存在缓存效应。
无论哪种方式,对于 500 行,3 秒都是减慢的方式,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*
);
相关:
关于performance - Postgres 主键 'less than' 运行缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41470221/