我目前有一个从作业表中随机选择作业的查询:
select jobs.job_id
from jobs
where (jobs.type is null)
and (jobs.project_id = 5)
and (jobs.status = 'Available')
offset floor(random() * (select count(*) from jobs
where (jobs.type is null) and (jobs.project_id = 5)
and (jobs.status = 'Available')))
limit 1
这具有所需的功能,但速度太慢。我正在使用Postgres 9.2,所以我不能使用TABLESAMPLE
。
从好的方面来说,我不需要它是真正随机的,所以我认为我可以通过使它稍微随机来优化它。
有什么想法吗?
答案 0 :(得分:1)
我可以建议jobs(project_id, status, type)
的索引吗?如果查询尚未在表中定义,那么这可能会加快您的查询速度。
答案 1 :(得分:0)
不使用OFFSET
和LIMIT
,为什么不使用
ORDER BY random() LIMIT 1
如果这也太慢,你可以替换你的子查询
select count(*) from jobs
where (jobs.type is null) and (jobs.project_id = 5)
and (jobs.status = 'Available')
类似
SELECT reltuples * <factor> FROM pg_class WHERE oid = <tableoid>
其中<tableoid>
是jobs
表的OID,而<factor>
是一个稍微大于子查询WHERE
条件选择性的数字。
这样可以节省一次顺序扫描,但有时你不会得到任何结果并且不得不重复查询。
这够好吗?
答案 2 :(得分:0)
一个脏技巧:将随机值存储在表中并在其上构建(部分)索引。 (您可能希望不时地重新随机化该字段,以避免记录永远不被选中; - )
-- assumed table definition
CREATE table jobs
( job_id SERIAL NOT NULL PRIMARY KEY
, type VARCHAR
, project_id INTEGER NOT NULL
, status VARCHAR NOT NULL
-- pre-computed magic random number
-- , magic DOUBLE PRECISION NOT NULL DEFAULT random()
);
-- some data to play with
INSERT INTO jobs(type,project_id,status)
SELECT 'aaa' , gs %10 , 'Omg!'
FROM generate_series(1,10000) gs;
UPDATE jobs SET type = NULL WHERE random() < 0.2;
UPDATE jobs SET status = 'Available' WHERE random() < 0.2;
-- add a column containing random numbers
ALTER TABLE jobs
ADD column magic DOUBLE PRECISION NOT NULL DEFAULT random()
;
CREATE INDEX ON jobs(magic)
-- index is only applied for the conditions you will be searching
WHERE status = 'Available' AND project_id = 5 AND type IS NULL
;
-- make sure statistics are present
VACUUM ANALYZE jobs;
-- EXPLAIN
SELECT j.job_id
FROM jobs j
WHERE j.type is null
AND j.project_id = 5
AND j.status = 'Available'
ORDER BY j.magic
LIMIT 1
;
类似的东西可以通过使用具有相当高的增量值(3G附近的一些素数)而不是随机+浮点数的串行来实现。