考虑下表
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行
如何加快选择主键小于变量的查询?
答案 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;
来更新计划。