扩展能够扩展,改变和推进Postgres的行为。怎么样?通过挂钩到低级Postgres API挂钩。 横向扩展Postgres的开源 Citus数据库本身实现为 PostgreSQL扩展,它允许Citus保持与Postgres版本保持同步,而不像其他Postgres分支那样落后。我之前已经写过关于 各种类型的扩展,虽然我想深入了解最有用的Postgres扩展: pg_stat_statements
。
你看,我刚从FOSDEM回来了。FOSDEM是布鲁塞尔的年度免费和开源软件会议,在此次活动中,我在PostgreSQL开发室中发表了关于Postgres扩展的演讲 。截至当天结束时,在Postgres开发室中提出的一半以上的会谈提到 pg_stat_statements
:
如果您使用Postgres并且尚未使用 pg_stat_statements
,则必须将其添加到工具箱中。即使你熟悉,也许值得重温一下。
pg_stat_statements入门
Pg_stat_statements
是所谓的contrib扩展,可以在contrib
PostgreSQL发行版的目录中找到 。这意味着它已经与Postgres一起提供,您不必从源代码或安装包中构建它。如果尚未启用,则可能必须为数据库启用它。这很简单:
CREATE EXTENSION pg_stat_statements;
如果您在主要云提供商上运行 ,他们很可能已经为您安装并启用了它。
一旦 pg_stat_statements
安装完毕,它就会开始默默地在封面下工作。Pg_stat_statements记录针对您的数据库运行的查询,从中删除多个变量,然后保存有关查询的数据,例如它花了多长时间,以及底层读/写发生了什么。
注意:它不保存每个单独的查询,而是对它们进行参数化,然后保存聚合结果。
让我们来看看如何使用几个例子。假设我们执行以下查询:
SELECT order_details .qty,
order_details .item_id,
order_details .item_price
FROM order_details,
顾客
WHERE客户.ID = ORDER_DETAILS .customer_id
与客户.email = '[email protected]'
它会将此查询转换为:
SELECT order_details .qty,
order_details .item_id,
order_details .item_price
FROM order_details,
顾客
WHERE客户.ID = ORDER_DETAILS .customer_id
和客户.email = '?'
如果这是我的应用程序中的一个查询,我经常执行以获取零售订单历史记录之类的订单详细信息,则不会保存为每个用户运行此操作的频率,而是保存聚合视图。
看数据
从这里我们可以查询原始数据, pg_stat_statements
我们会看到类似的东西:
选择 *
来自 pg_stat_statements;
userid | 16384
dbid | 16388
查询| select * from users where email = ?;
电话| 2
total_time | 0.000268
行| 2
shared_blks_hit | 16
shared_blks_read | 0
shared_blks_dirtied | 0
shared_blks_written | 0
local_blks_hit | 0
local_blks_read | 0
local_blks_dirtied | 0
local_blks_written | 0
...
使用pg_stat_statements提取数据分析
现在,这里有大量有价值的信息,作为一个更高级的用户,有时它们都可以证明是有价值的。但即使没有开始理解数据库的内部,您也可以通过pg_stat_statements
某些方式查询来获得一些非常强大的见解 。通过查看 total_time
每个查询调用查询的次数和次数,我们可以非常快速地查看经常运行的查询以及它们平均消耗的内容:
选择
(TOTAL_TIME / 1000 / 60)作为总,
(total_time / calls)as avg,
询问
来自 pg_stat_statements
ORDER BY 1个 DESC
限制 100 ;
您可以通过多种不同的方式对此进行过滤并对其进行排序,您可能只想关注运行超过1,000次的查询。或者平均超过100毫秒的查询。上面的查询向我们显示了对数据库消耗的总时间(以分钟为单位)以及以毫秒为单位的平均时间。通过上面的查询,我会得到一些看起来像:
总计| 平均| 询问
-------- + -------- + -------------------------
295.76 | 10.13 | SELECT id FROM users ...
219.13 | 80.24 | SELECT * FROM ...
(2排)
根据经验,我知道当快速抓取记录时,PostgreSQL应该能够在1ms内 返回。鉴于此,我可以进行优化工作。在上面我看到将第一个查询降低到1毫秒将是一个改进,但优化第二个查询将为我的整个系统提供更大的性能提升。
特别说明:如果您正在构建 多租户应用,则可能不希望pg_stat_statements参数化您的 tenant_id
。为了解决这个问题,我们构建了citus_stat_statements来为您提供 每个租户的见解。
如果你还没有看过你的数据 pg_stat_statements
- 甚至在过去的一个月 - 今天是一个美好的一天。它告诉你什么可以优化的地方?