DB2数据更新问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DB2数据更新问题相关的知识,希望对你有一定的参考价值。

开发工具:PB
数据库:DB2
需要更新客户的零件价格信息和其他的相关信息,每次更新数据会有2800000条左右,目前的程序需要执行11个小时才可以完全结束。
实现方法是用DATASTORE来Update的,客户仍然感觉很慢,请教各位大神,有什么其他的好一点的办法可以进一步的提高效率吗?

按照你的说法,是先从一个表(假定表名为A)里读取1000行数据,然后到正式表(假定表名为B)里分别判断每条记录,如果没有这条记录就INSERT到正式表,如果正式表有这条记录就UPDATE正式表的数据,然后再处理下一个1000行。我这个理解正确吗?

如果是这样的话,从A表取数据的WHERE条件中的谓词应该建成一个复合索引,并且排序字段建成一个单独的索引(rownumber() over(order by 排序字段 asc ) as rowid),这样能很大程度上加快读的速度,这个语句频繁执行,是优化的关键点。
接下来判断每条记录在B表是否存在,这个WHERE条件中的谓词也应该建成一个复合索引,因为这个语句会频繁执行,也是优化的关键点。
然后是判断,不知道你用的是什么语言来实现,这个地方已经跟数据库没有关系了,无法优化。

接下来是插入,如果能批量操作,就考虑批量,比如JDBC的接口中addBatch()等方法,同时给B表添加append on特性,可以很大程度的加快插入速度,是优化的关键点。使用append 特性以后,请注意定期reorg table,alter table TAB_NAME append on。
接下来是更新,同样是做成批量操作,这个UPDATE的WHERE条件中的谓词也建成一个复合索引,这个语句频繁执行,也是优化的关键点。

然后数据库层面:
日志缓冲池(LOGBUFSZ)调整成8192个页面,可以减少日志I/O,这个也是优化的关键点;
活动日志、归档日志所在的磁盘与数据所在的磁盘要分开,因为I/O是数据库最耗时的操作,瓶颈一般都处在这个地方,这个也是优化的关键点;
数据和索引及大字段分开存放在不同的表空间,数据和索引不要用文件缓存,大字段启用文件缓存;
索引使用的缓冲池最好保证索引完全能够容纳进去,这样能很大的加快查询速度,这也是优化的关键点;
日志文件大小最好定义为100MB,主日志大小定义为10,辅助日志大小定义为20,即LOGFILSIZ=25600,LOGPRIMARY=10,LOGSECOND=20,这样可以减少日志频繁归档和保证一个事务可以进行更多的DML操作;
每次操作不要只对1000行记录进行操作就提交,因为频繁提交很耗时,建议调整为每次2W条,上面所说的日志配置应该足够确保不会出现日志空间满的问题。

我在银行的批处理操作中做过12个参数表的这种临时表、正式表、查询、判断、INSERT、UPDATE的操作,总数据量有14W条记录,操作时间都是在10分钟以内结束,而且是一台服务器上三个环境都有这样的作业在同时执行(即访问临时表和正式表中不同的记录)。
按照这个估算,你的280W条记录,应该可以在200分钟内结束。

我程序中用到的是JAVA、MYBATIS、SPRING的手动事务。
附:我拥有DB2 V9的所有认证,希望我的回答对你有所帮助。
参考技术A update本身是比较慢的,你可以将更新的条件增加索引,必要的时候增加组合索引.
其实最好是整型的数字字段,比如主键作为条件,能很大的提高速度.
另外,你可看表的数据量,如果更新的数据是全部,或者是绝大部分,建议你把不更新的导出,然后分别插入不更新的,和已经修改过的价格.追问

恩,有一张的表的数据比较多,考虑过你说的,现在正在和客户沟通,因为他们有可能会取那张表的历史数据。可以将更新的东西写到存储过程吗,那样会不会快一点。

追答

存储过程也是追条执行的,性能上没啥差别的.
如果历史数据是增量,且访问不频繁,建议单独存放一张表;
而经常访问的实时(每次更新的)数据,也单独放一张表;
这样做可能会增加一个界面,或者说走个分支接口,但是对客户体验上来说性能还是有很大提高的.
另外,可以考虑分区(比如按照时间,这种分区方式较为常用),这个你可以研究下.

追问

按照现在程序里面的逻辑,历史数据的确是增量,理论上来说,客户是不会取很早之前的数据的,之前我们也考虑过分两张表存放,但是现在客户也没有具体回复,所以我们也没法决定对那部分历史数据的处理方案。
现在我正在对每部分的时间做测试,看那部分花的时间最长,到时候在做优化吧。

追答

客户没回复,你也只能在现有的基础上优化了,加油~

参考技术B 批量的去更新,每次批量设置一定数量,如1000条或10000条commit一次。追问

现在就是这么处理的,但是每一条都需要去表里校验有没有这个数据,有就UPDATE,没有就INSERT。也是挺耗费时间的。

当我想使用 db-migration 更新数据库时,如何防止数据丢失?

【中文标题】当我想使用 db-migration 更新数据库时,如何防止数据丢失?【英文标题】:How to prevent data loss when I want to update database by using db-migration? 【发布时间】:2014-12-16 13:06:40 【问题描述】:

当我使用 db-migration 更新我的数据库时,我遇到了一个问题

Automatic migration was not applied because it would result in data loss.

(对于某些属性,我使用了System.ComponentModel.DataAnnotations,例如[Required][StringLength(25)]。例如Title 属性。)

我知道如果我将AutomaticMigrationDataLossAllowed 设置为trueUpdate-Database -Force,我的数据库将被更新,但我的数据将被删除,我将阻止它。我想保护我的数据。

我用过 Entity Framework 6.x

我该如何解决这个问题?

配置类:

namespace Jahan.Blog.Web.Mvc.Migrations

   using System;
   using System.Data.Entity;
   using System.Data.Entity.Migrations;
   using System.Linq;

   internal sealed class Configuration 
    : DbMigrationsConfiguration<Jahan.Blog.Web.Mvc.Models.JahanBlogDbContext>
   
       public Configuration()
       
           AutomaticMigrationsEnabled = true;
           AutomaticMigrationDataLossAllowed = false;
       

       protected override void Seed(Jahan.Blog.Web.Mvc.Models.JahanBlogDbContext context)
       

       
   

初始类:

namespace Jahan.Blog.Web.Mvc.Migrations

   using System;
   using System.Data.Entity.Migrations;

   public partial class Initial : DbMigration
   
       public override void Up()
       
       

       public override void Down()
       
       
   

我的 DbContext:

namespace Jahan.Blog.DataAccess

   public class JahanBlogDbContext : IdentityDbContext<User, Role, int, UserLogin, UserRole,    UserClaim>
   
       public JahanBlogDbContext()
           : base("name=JahanBlogDbConnectionString")
       

       
       protected override void OnModelCreating(DbModelBuilder modelBuilder)
       
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Entity<Comment>().HasRequired(t => t.Article).WithMany(t => t.Comments).HasForeignKey(d => d.ArticleId).WillCascadeOnDelete(true);
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<User>().ToTable("User");
        modelBuilder.Entity<Role>().ToTable("Role");
        modelBuilder.Entity<UserRole>().ToTable("UserRole");
        modelBuilder.Entity<UserLogin>().ToTable("UserLogin");
        modelBuilder.Entity<UserClaim>().ToTable("UserClaim");
       
       // ... codes ....
   

【问题讨论】:

【参考方案1】:

您可以添加 sql 以您可以接受的方式修复数据。您需要确保 EF 生成的 alter statements 不会导致数据丢失。

在迁移中使用Sql 方法运行您自己的sql:

public override void Up()

    //Add this to your migration...
    Sql("UPDATE dbo.Table SET Name = LEFT(Name, 25) WHERE LEN(Name) > 25")

    //...before the code generated by EF
    AlterColumn("dbo.Table", "Name ", c => c.String(nullable: false, maxLength: 25));

【讨论】:

请指定我应该在哪里添加此代码?在哪个文件中? 您应该将它放在添加迁移时生成的迁移文件的Up 方法中,在对模型进行任何更改后必须这样做。 msdn.microsoft.com/en-gb/data/jj591621 您的评论很有用,我的数据库已更新。(我在 SqlServer 中看到数据库,一切正常)但是程序运行时出现错误......支持'的模型自数据库创建以来,JahanBlogDbContext 的上下文已更改。考虑使用 Code First 迁移来更新数据库 (go.microsoft.com/fwlink/?LinkId=238269)。 我从数据库中删除了 __MigrationHistory 表的记录。我的程序现在运行成功! 如果我想通过 db-migration 确定数据库中某个字段的值范围,应该怎么做? ...***.com/questions/26493019/…

以上是关于DB2数据更新问题的主要内容,如果未能解决你的问题,请参考以下文章

[db2数据库数据同步解决方案]DB2数据库数据同步更新方法及设备与流程

如何查看 db2 服务器中最近更新的表?

DB2 更新触发器

db2 我先DROP掉一张表,再重建,再LOAD数据进这张表,之后对这个表做UPDATE操作很慢,这是为啥

DB2数据库更新数据缓慢,求优化建议

如何在没有超时的情况下锁定 Ibm Db2 中的更新行?