我有一个语句将一堆行(这个问题的内容或位置并不重要)插入到 Postgres 数据库中,但它没有我想要的那么快。我可以运行一个解释查询来查看它在做什么,我得到如下信息:
Insert on dpdb.datapoints (cost=0.00..6917.76 rows=44184 width=1786) (actual time=15558.623..15558.623 rows=0 loops=1)
Buffers: shared hit=34670391 read=98370 dirtied=48658 written=39875
I/O Timings: read=704.525 write=242.915
-> Seq Scan on public.fred (cost=0.00..6917.76 rows=44184 width=1786) (actual time=0.018..197.853 rows=44184 loops=1)
Output: nextval('datapoints_id_seq'::regclass), fred.company_id, fred.tag, ... lots more columns ...
Buffers: shared hit=44186 read=6253 dirtied=1
I/O Timings: read=29.176
Planning time: 0.110 ms
Trigger RI_ConstraintTrigger_c_14845718 for constraint datapoints_tag_source_fkey: time=236.677 calls=44184
Trigger RI_ConstraintTrigger_c_14845723 for constraint datapoints_sheet_type_fkey: time=536.367 calls=44184
Trigger RI_ConstraintTrigger_c_14845728 for constraint datapoints_subcontext_fkey: time=178.200 calls=44184
Trigger RI_ConstraintTrigger_c_14845733 for constraint datapoints_source_type_fkey: time=467.619 calls=44184
Trigger RI_ConstraintTrigger_c_14845738 for constraint datapoints_doc_type_fkey: time=302.256 calls=44184
Trigger RI_ConstraintTrigger_c_14845743 for constraint datapoints_comment_type_fkey: time=88.740 calls=44184
Trigger RI_ConstraintTrigger_c_14845748 for constraint datapoints_preferred_dpid_fkey: time=33.313 calls=44184
Execution time: 17432.381 ms
(16 rows)
这很棒,因为我看到了各种触发器的成本和查询的选择部分,但如果我将所有这些部分加起来,它大约是 2 秒(不到总时间的 10%)。除了花了大约 24 秒之外,它并没有告诉我更多关于实际插入的信息。我猜测成本的很大一部分是更新索引,但我不确定这一点。我如何获得正在更新的索引以及每个索引的相对成本的分割?这甚至可能吗?(我最初在 dba.stackexchange.com 上问过这个问题,但没有任何答案——它介于 DBA 和开发问题之间,所以我想我会在这里问)
最佳答案
那些看起来像外键约束。每个插入都在执行 SELECT
检查该行是否存在,希望使用假设该索引存在的索引。
时间差异是因为time
在每个触发器上向您显示执行函数所花费的时间,不包括 IO 等待时间。换句话说,它没有显示挂钟时间,而是显示 CPU 时间(大约)。
您可以使用 pg_stat_statements尝试查看对这些表的查询并找到外键,但在一天结束时,这对于使用外键来说看起来很正常。
如果您需要这些插入更快地执行,最好的选择是删除外键约束。
关于postgresql - 分析 postgres 中插入的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64124804/