Mic*_*ler 3 mysql postgresql performance sql-update
假设我有一个主键列表,每行需要更新一个值.运行是否更好:
-- run 10,000 of these queries
UPDATE mytable SET myflag = 1 WHERE id = [each_id]
Run Code Online (Sandbox Code Playgroud)
或者将更新组合成批量查询,如下所示:
-- run 100 of these queries, where the IN () list contains about 100 elements
UPDATE mytable SET myflag = 1 WHERE id IN (3, 4, 5, 9, 99, ... 7887 )
Run Code Online (Sandbox Code Playgroud)
100个IN()项目的100个查询怎么样?
都不是.在PostgreSQL中我会改为:
WITH x AS (
SELECT unnest('{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60
,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80
,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
}'::int[]) AS id
)
UPDATE mytable t
SET myflag = 1
FROM x
WHERE t.id = x.id;
Run Code Online (Sandbox Code Playgroud)
我在我的例子中添加了很多ID,以提供10000个ID很多的视觉线索.问题中提出的两个想法是:
必须解析列表并将10000个语句放在一起并将它们发送到服务器,这可能需要比UPDATE本身更长的时间.
具有在10000项为每个单独的列表(阵列)来搜索id在mytable用于匹配的ID.不能使用标准索引.这将非常缓慢.性能随着大小而降低mytable.
索引mytable.id是所有提出的替代需求,以超过一个数量级的两个变体.
该CTE解析阵列一次(子查询的作品,太- MySQL有没有热膨胀系数) -并且unnest()是相当快这一点.在一个语句中完成所有操作可以使10000个语句超过一个数量级.如果这些语句在单个事务中运行,则添加另一个数量级.如果您应该使用单个会话,请添加另一个.
极少数例外适用于在大量写入负载下具有锁定问题的数据库 正如已建议的那样只是基准.EXPLAIN ANALYZE是你在PostgreSQL的朋友.
如果操作增长巨大,且大部分表的更新和/或你的磁盘空间或内存不足时,它可能仍然是一个好主意,操作分成几个逻辑块-只是不太多,找到甜蜜点.主要是让HOT更新回收之前UPDATE运行的表膨胀.考虑这个相关的问题.
| 归档时间: |
|
| 查看次数: |
3126 次 |
| 最近记录: |