我有一张大桌子:
CREATE TABLE "orders" (
"id" serial NOT NULL,
"person_id" int4,
"created" int4,
CONSTRAINT "orders_pkey" PRIMARY KEY ("id")
);
所有请求的90%是关于person_id
过去2-3天的订单,例如:
select * from orders
where person_id = 1
and created >= extract(epoch from current_timestamp)::int - 60 * 60 * 24 * 3;
如何改善表现?
我知道Partitioning,但现有行怎么样?看起来我需要每2-3天手动创建INHERITS
个表。
答案 0 :(得分:3)
我建议在(person_id, created)
IMMUTABLE
上使用伪CREATE OR REPLACE FUNCTION f_orders_idx_start()
RETURNS integer AS
'SELECT 1387497600'
LANGUAGE sql IMMUTABLE COST 1;
条件,需要不时重新创建以保持效果。
注意,如果你的表不是很大,你可以在很大程度上简化和使用普通的多列索引。
原始函数提供一个恒定的时间点,3天或更长时间(在您的情况下由unix时期表示):
1387497600
SELECT extract(epoch from now())::integer - 259200;
是IMMUTABLE
的结果。
将部分索引基于此伪CREATE INDEX orders_created_recent_idx ON orders (person_id, created)
WHERE created >= f_orders_idx_start();
条件:
SELECT *
FROM orders
WHERE person_id = 1
AND created >= f_orders_idx_start() -- match partial idx. condition
AND created >= extract(epoch from now())::integer - 259200;
-- 259200 being the result of 60 * 60 * 24 * 3
将查询基于相同的“常量”:
AND created >= f_orders_idx_start()
行CREATE OR REPLACE FUNCTION f_orders_reindex_partial()
RETURNS void AS
$func$
DECLARE
-- 3 days back, starting at 00:00
_start int := extract(epoch from now()::date -3)::int;
BEGIN
IF _start = f_orders_idx_start() THEN
-- do nothing, nothing changes.
ELSE
DROP INDEX IF EXISTS orders_created_recent_idx;
-- Recreate IMMUTABLE function
EXECUTE '
CREATE OR REPLACE FUNCTION f_orders_idx_start()
RETURNS integer AS
$$SELECT ' || _start || '$$
LANGUAGE sql IMMUTABLE COST 1';
-- Recreate partial index
CREATE INDEX orders_created_recent_idx ON orders (person_id, created)
WHERE created >= f_orders_idx_start();
END IF;
END
$func$ LANGUAGE plpgsql;
似乎是多余的,但有助于说服Postgres使用部分索引。
功能,可以不时重新创建功能和索引。可能每晚都有一份cron-job:
SELECT f_orders_reindex_partial(); -- that's all
呼叫:
CREATE INDEX orders_created_recent_idx ON orders (person_id, created, id)
WHERE created >= f_orders_idx_start();
即使您从未调用此函数,所有查询仍可继续工作。随着部分指数的增长,业绩会逐渐恶化。
我正在成功使用这个政权,有几个大表和类似的要求。 非常快。
对于Postgres 9.2或更高版本,并且如果您的表只有很少的小列,并且如果表格没有大量编写,则可能需要支付partial multicolumn index:
{{1}}
答案 1 :(得分:0)
建议: -
它可能对你有所帮助。 由于表大小不断增长,您的查询性能将逐渐降低。更好地维护3-5天(如果您非常确定只能访问2-3天)记录并定期将旧记录迁移到备份表。