【发布时间】:2012-07-08 01:48:59
【问题描述】:
我的问题是我对一个有 1400 万行的表的更新查询非常慢。我尝试了不同的方法来调整我的服务器,这带来了良好的性能,但不适用于更新查询。
我有两张桌子:
- T1 上有 4 列和 3 个索引(530 行)
- T2 上有 15 列和 3 个索引(1400 万行)
- 我想通过在文本字段 stxt 上连接两个表,将 T2 中的字段 vid(整数类型)更新为 T1 中相同的 vid 值。
这是我的查询及其输出:
explain analyse
update T2
set vid=T1.vid
from T1
where stxt2 ~ stxt1 and T2.vid = 0;
T2 更新(成本=0.00..9037530.59 行=2814247 宽度=131)(实际时间=25141785.741..25141785.741 行=0 循环=1)
-> 嵌套循环(成本=0.00..9037530.59 行=2814247 宽度=131)(实际时间=32.636..25035782.995 行=679354 循环=1)
加入过滤器:((T2.stxt2)::text ~ (T1.stxt1)::text)
-> T2 上的 Seq Scan(成本=0.00..594772.96 行=1061980 宽度=121)(实际时间=0.067..5402.614 行=1037809 循环=1)
过滤器:(视频= 1)
-> 实现(成本=0.00..17.95 行=530 宽度=34)(实际时间=0.000..0.069 行=530 循环=1037809)
-> T1 上的 Seq Scan(成本=0.00..15.30 行=530 宽度=34)(实际时间=0.019..0.397 行=530 循环=1)
总运行时间:25141785.904 毫秒
如您所见,查询耗时约 25141 秒(约 7 小时)。 f 我理解得很好,planner 估计执行时间为 9037 秒(~ 2.5 小时)。我在这里遗漏了什么吗?
以下是有关我的服务器配置的信息:
- CentOS 5.8,20GB 内存
- shared_buffers = 12GB
- work_mem = 64MB
- maintenance_work_mem = 64MB
- bgwriter_lru_maxpages = 500
- checkpoint_segments = 64
- checkpoint_completion_target = 0.9
- 有效缓存大小 = 10GB
我已经在 T2 表上运行了 Vacuum full 并分析了几次,但这仍然没有改善这种情况。
PS:如果我将 full_page_writes 设置为关闭,这会大大改善更新查询,但我不想冒数据丢失的风险。请问您有什么建议吗?
【问题讨论】:
-
尝试改用 MERGE。它可以更快地链接表格。
-
你真的需要 ~ 操作符吗? stxt1、stxt2 字段中有什么,它们的类型是什么?
-
@wildplasser ~ 运算符几乎等同于
stxt2 like '%'||stxt1||'%'。两个字段 stxt 都是不同的字符。 @radashk 我试过这个 link 但 Postgres 一直告诉我ERROR: syntax error at or near "MERGE"。我应该如何尝试“合并”? -
1) 我知道 ~ 是什么意思,但您似乎在 table1 中存储了 500 个正则表达式。 2) postgresql 中没有合并(在这种情况下也无济于事)
-
@wildplasser 我不知道是否有另一种方法可以连接这两个表,这就是我使用 ~ 的原因。如果 stxt2 包含 stxt1,那么我希望 T2.vid 等于 T1.vid,否则什么都不会发生。感谢您的帮助。
标签: regex performance postgresql