是否有一个插件或脚本可以跟踪PostgreSQL中长查询的进度?
我的意思是我需要在Java中设置与Postgres中的某些更新查询相关的进度条值.我通过互联网搜索,但我刚发现一些文件在任何RDBMS系统中都没有任何官方实现.
jjr*_*jrv 22
我在这里找到了一个很好的答案:跟踪更新声明的进度
诀窍是首先创建一个序列(根据需要命名):
CREATE SEQUENCE query_progress START 1;
Run Code Online (Sandbox Code Playgroud)
然后附加到查询的WHERE部分:
AND NEXTVAL('query_progress')!=0
Run Code Online (Sandbox Code Playgroud)
现在您可以查询进度:
SELECT NEXTVAL('query_progress');
Run Code Online (Sandbox Code Playgroud)
最后不要忘记摆脱序列:
DROP SEQUENCE query_progress;
Run Code Online (Sandbox Code Playgroud)
请注意,这很可能会使您的查询运行速度更慢,每次检查进度时它都会增加值.上面的链接建议创建一个临时序列,但PostgreSQL似乎不会使它们在会话中可见.
我想出了一个可能有帮助的方法。但是,如果您想将其实现到您的代码(如 Java 等)中,则可能需要进一步处理。
方法是检查页面内容以跟踪进度。
Postgresql 有一个名为 pageinspect 的扩展,可以检查特定表的页面信息。
此处的详细信息:https : //www.postgresql.org/docs/current/pageinspect.html
也花一些时间在这里了解 postgresql 的页面布局
https://www.postgresql.org/docs/current/storage-page-layout.html
特别查看 xmin、xmax 和 ctid
我假设表中的行插入遵循特定顺序。就像桌子的钥匙一样。任何长时间的更新都可能会附加新页面。
我还假设主键 id 大部分是连续的,几乎没有间隙。既然只是估计,我觉得这个条件还可以。
但是,您无法通过这样做找出总页码SELECT relname, relpages FROM pg_class,因为它没有更新。
如果页面索引在 strage 中不存在,您将遇到异常(但您会找到该页面,即使它没有在 pg_class 左右更新),因此在“page_index”上进行一点“二进制搜索”以找到您拥有的最大页面。不需要很准确。
用
SELECT backend_xid FROM pg_stat_activity WHERE pid = process-id
Run Code Online (Sandbox Code Playgroud)
查找您当前的交易 ID。
用
SELECT lp,t_xmin,t_xmax,t_ctid,t_bits,t_data FROM heap_page_items(get_raw_page('relation_name', page_index));
Run Code Online (Sandbox Code Playgroud)
在我正在处理的示例中,它可能看起来像这样
SELECT lp,t_xmin,t_xmax,t_ctid,t_bits,t_data FROM heap_page_items(get_raw_page('foo', 3407000));
LP | t_xmin | t_xmax | t_ctid | t_bits | t_data
1 | 592744 | 592744 | (3407000,1) | 110000000111000000000000 | \xd1100000000000000e4400000000000054010000611b0000631b0000
2 | 592744 | 592744 | (3407000,2) | 110000000111000000000000 | \xd110000000000000104400000000000040010000611b0000631b0000
3 | 592744 | 592744 | (3407000,3) | 110000000111000000000000 | \xd11000000000000011440000000000007c010000611b0000631b0000
t_data 是数据。lp 是项目列表中的元组索引。t_xmin 和 t_xmax 是事务 ID。并且 t_ctid 是元组本身中元组的点。如果元组中有空值,则 t_bits 是 NULL 位图。
首先查看t_min = t_max,和t_ctid(page_index, tuple_id)和lp是否相同。如果是,请检查 t_xmin 是否与您的交易 ID 相同。如果是这样检查数据。
注意字节序和空位图。就我而言,它是大端(LSB 优先)。
在我的示例中,第一行是有效的。第一个 BIGINT(8 个字节 16 个十六进制数)是我正在查找的排序 ID。所以第一行的数据是
\xd110000000000000
转换为 0x101d(检查字节序)--> 4305
我知道我最大的 id 是 18209,smallest_id 是 2857。我把工作分成 8 部分,所以
(18209 - 2857) / 8 = 1919
这是我运行的第一部分。所以
2857 + 1919 = 4776
这意味着我的子作业从 2857 id 开始,目前在 4305。如果它达到 4776,这个线程就完成了!
这是
(4305 - 2857)/ 1919 = 75.5% 完成
限制
这不适用于哈希值更新。在我的情况下,id 恰好作为 pkey 顺序排序。规划器触发顺序读取。如果规划器正在执行某种 btree 索引扫描以进行更新,这也应该有效。
如果您有兴趣按索引顺序对物理行进行排序,请查看CLUSTER。
同样,这种方法并不准确。并根据上面强调的假设。如果在程序中使用,应该使用 sparsely 以防止磁盘 I/O 的额外开销
| 归档时间: |
|
| 查看次数: |
9250 次 |
| 最近记录: |