Postgresql 优化Postgres时间戳查询范围
我定义了下表和索引:Postgresql 优化Postgres时间戳查询范围,postgresql,indexing,query-optimization,database-partitioning,postgresql-performance,Postgresql,Indexing,Query Optimization,Database Partitioning,Postgresql Performance,我定义了下表和索引: CREATE TABLE ticket ( wid bigint NOT NULL DEFAULT nextval('tickets_id_seq'::regclass), eid bigint, created timestamp with time zone NOT NULL DEFAULT now(), status integer NOT NULL DEFAULT 0, argsxml text, moduleid character var
CREATE TABLE ticket
(
wid bigint NOT NULL DEFAULT nextval('tickets_id_seq'::regclass),
eid bigint,
created timestamp with time zone NOT NULL DEFAULT now(),
status integer NOT NULL DEFAULT 0,
argsxml text,
moduleid character varying(255),
source_id bigint,
file_type_id bigint,
file_name character varying(255),
status_reason character varying(255),
...
)
我在created
时间戳上创建了一个索引,如下所示:
CREATE INDEX ticket_1_idx
ON ticket
USING btree
(created );
这是我的问题
select * from ticket
where created between '2012-12-19 00:00:00' and '2012-12-20 00:00:00'
在唱片数量开始增长(约500万张)之前,这一切都运转良好,现在它要花很长时间才能恢复
解释分析揭示了这一点:
"Index Scan using ticket_1_idx on ticket (cost=0.00..10202.64 rows=52543 width=1297) (actual time=0.109..125.704 rows=53340 loops=1)"
" Index Cond: ((created >= '2012-12-19 00:00:00+00'::timestamp with time zone) AND (created <= '2012-12-20 00:00:00+00'::timestamp with time zone))"
"Total runtime: 175.853 ms"
也创造
create CLUSTER ticket USING ticket_1_idx;
什么都不管用。我做错了什么?为什么选择顺序扫描?索引应该使查询速度更快。可以做些什么来优化它
如果要使用群集
,则显示的语法无效
使用ticket\u 1\u idx创建集群ticket代码>
运行一次:
CLUSTER ticket USING ticket_1_idx;
这对更大的结果集有很大帮助。对于返回的一行,没有这么多。
Postgres会记住后续调用要使用的索引。如果您的表不是只读的,效果会随着时间的推移而恶化,您需要每隔一定的时间重新运行:
CLUSTER ticket;
可能只在易失性分区上。见下文
但是,如果有大量更新,集群
(或真空满
)实际上可能对性能有害。适当的膨胀量允许UPDATE
将新行版本放在同一数据页上,并避免了在操作系统中过于频繁地物理扩展底层文件的需要。您可以使用经过仔细调整的FILLFACTOR
来充分利用这两个方面:
CLUSTER
对表进行独占锁定,这在多用户环境中可能是个问题
当对表进行集群时,将获取一个访问独占
锁
在上面。这将防止任何其他数据库操作(读取和
从对表的操作开始写入,直到集群完成
我的。考虑:
与集群
和真空满负荷
不同,它可以在线工作,无需持有
处理期间对已处理表的独占锁定。pg_重新包装是
引导效率高,性能可与直接使用集群
媲美
以及:
pg_repack需要在重组结束时获得独占锁
1.3.1版适用于:
PostgreSQL 8.3、8.4、9.0、9.1、9.2、9.3、9.4
版本1.4.2适用于:
PostgreSQL 9.1、9.2、9.3、9.4、9.5、9.6、10
查询
查询本身非常简单,不会导致任何性能问题
然而,一个关于正确性的词:构造包括边界。您的查询将选择12月19日的所有记录,以及12月20日00:00小时的记录。这是一个极不可能的要求。很可能,你真的想要:
SELECT *
FROM ticket
WHERE created >= '2012-12-19 0:0'
AND created < '2012-12-20 0:0';
在新月份开始前创建一个新索引。您可以使用cron作业轻松地自动化任务。
可以选择删除旧月份的部分索引
除了集群
(不能对部分索引进行操作)之外,还要保留总索引。如果旧记录从未更改,那么表分区将大大有助于完成此任务,因为您只需要重新对新分区进行集群。
同样,如果记录从未更改,您可能不需要使用集群
如果将最后两个步骤结合起来,性能应该会非常出色
性能基础
您可能缺少其中一个基本要素。所有通常的性能建议均适用于:
它没有进行顺序扫描。它正在进行索引扫描,而且只需要175毫秒就可以运行。如果要花很长时间,OP可能有一个巨大的数据集,需要很长时间才能通过网络传输,而不是运行查询。\BTW:effective\u cache\u size=3
可能有点太低了。(但在这种情况下可能不会伤害)为什么你考虑175MS“AGE”?不要做<代码>选择*<代码>,因为它会增加结果集的大小以转移到客户端。
SELECT *
FROM ticket
WHERE created >= '2012-12-19 0:0'
AND created < '2012-12-20 0:0';
CREATE INDEX ticket_created_idx ON ticket(created)
WHERE created >= '2012-12-01 00:00:00'::timestamp;