数据库快速更新全表数据
来源:互联网 发布:淘宝徐志摩诗集大全 编辑:程序博客网 时间:2024/06/05 09:09
备注:以下更新的算法适合所有数据库,示例采用PostgreSQL,其它数据库只用修改语法即可.
题外话:软件思想很重要,不要局限于某种语言\工具\数据库,思想才是最重要的.有时候一个灵光一闪的想法说不定就是一个好的软件.
开始谈正事,在update全表数据时,常规写法下大家经常抱怨更新太慢,语句如下:
update 表 set 字段1=0,字段n=n
实际上这里由于在update前,数据库需要读取整个表,然后才开始update,所以上面的语句可以分成两步看
select * from 表update 表 set 字段1=select.字段,字段n=select.字段n where 主键=select.主键
select是一个全表扫描,update慢的原因主要就是这里了.
知道了问题所在,现在要想办法避开全表扫描,使用PRIMARY KEY扫描,并且不一次更新完,而是分批次更新,直到全表数据更新完成.
示例采用PostgreSQL数据库
1.创建测试表
drop table if exists test;create table test( objectid bigint not null, name text not null, describe jsonb, flag integer default(2) not null, /*演示要更新的字段*/ constraint pk_test_objectid primary key (objectid) with (fillfactor=60)) with (fillfactor=60);
经常更新的表建议设置fillfactor系数以提升Update和delete性能,默认为90.
2.创建随机生成中文字符函数
drop function if exists gen_random_zh(int,int);create or replace function gen_random_zh(int,int) returns textas $$select string_agg(chr((random()*(20901-19968)+19968 )::integer) , '') from generate_series(1,(random()*($2-$1)+$1)::integer);$$ language sql;
注意:这个函数是sql语言函数
3.导入数据函数
--$1为起始编号,每调用一次写入1000000条记录drop function if exists ins_test(bigint);create or replace function ins_test(bigint) returns voidas $$ declare begin for i in 1..1000 loop insert into test(objectid,name) select( (id + (i-1)*1000) + ($1 - 1) )as objectid,gen_random_zh(8,32) as name from generate_series(1,1000) as id; --raise notice '%', i; end loop; end;$$ language plpgsql;
注意:这个函数是plpgsql语言函数
4.导入1千万数据
导入1000万测试数据,为提高效率,开10个进程导入,每个写入100万.
根据机器配置不同,每次执行时间约20秒至几分钟不等.
select ins_test(1);select ins_test(1000001);select ins_test(2000001);select ins_test(3000001);select ins_test(4000001);select ins_test(5000001);select ins_test(6000001);select ins_test(7000001);select ins_test(8000001);select ins_test(9000001);
为节约时间全部导入完成后用以下命令统计表信息
analyze test;
5.更新数据
5.1常规方法
没有测试,肯定很慢
update test set flag=1;analyze test;
5.2分批层逐条更新
do $$declare v_currentid bigint;v_rec record;v_index integer;v_isok boolean;beginv_currentid := 0; v_index := 0;loopv_isok := false;v_index := v_index + 1;for v_rec in select objectid from test where objectid>v_currentid order by objectid limit 1000 loopupdate test set flag=1 where objectid=v_rec.objectid;v_isok:=true;v_currentid := v_rec.objectid;end loop;--raise notice '%,%', v_index,v_currentid;if( false = v_isok ) thenreturn;end if;end loop;end;$$;--Time: 320023.745 msanalyze test;
6.其它
更加复杂的方法是多次执行分批次更新,就如同第3节中的方法一样.
如果你有更好的方法请发邮件给我81855841@qq.com
如果你要监控过程,请删除raise之前的注释.
请记住:大数据处理分片处理是最基本的思想,再此之上结合需求和算法从而高效的完成工作任务.
阅读全文
0 0
- 数据库快速更新全表数据
- 数据库表快速更新
- 如何快速更新数据库中的百万条数据
- 快速备份/更新数据
- 快速批量更新数据
- 数据库数据更新,不同表,不同数据库的更新方式
- 批量更新数据库表数据-addBath()作用
- 数据库表的更新和修改数据
- Sybase数据库超大表数据矫正更新
- 数据库数据更新
- 数据库数据更新
- 数据库:数据更新
- thinkphp更新数据库数据
- PHP更新数据库数据
- 快速复制数据库表中的数据SQL
- 数据库快速插入数据
- 全表更新
- Enterprise Library 4.1数据访问应用程序块快速入门【6】使用DataSet更新数据库
- 同步和Java内存模型 Volatile
- 查找数据库指定数据的数据表和字段名称SQL语句
- IPv6路在何方(一)
- JAVA课程3 FOR语句8+88+888+8888前十项之和
- 声学模型GMM-HMM训练
- 数据库快速更新全表数据
- 为什么那么牛逼的财报都换不来任正非的乐观?
- Ubuntu下vim使用不了,怎么安装
- Java double 值保留两位小数4种方法
- JavaScritp 中变量的赋值和引用(续),在所有的children中查找某一id的节点并返回
- 重金投资打车应用,汽车公司和互联网巨头们都图什么?
- 6月4日vivo或将发布宋仲基代言新机 三大功能猜想
- 豆瓣影视改编上线 IP运营能否杀出重围?
- 判断日期是否在7天之内