totoo130 发表于 2011-03-28 19:34

关于MQT的用法【转】

转自 http://www.db2china.net/home/space.php?uid=24415&do=blog&id=10732

             最近用了MQT,mark一下用法和心得。
         物化查询表(MQT)是一种以一次查询的结果为基础定义的表。包含在物化查询表中的数据来自定义物化查询表时所基于的一个或多个表。MQT应该是对用户透明的,好处在于你想用MQT表来优化性能不需要修改代码。MQT 在数据仓库和商业智能方面运用的比较多,特别适用于海量数据的筛选。适合通过维表查取事实表数据。对数据量不大,表关系复杂的情况,效果不是很好。(下面会有试验)
      MQT使用的先决条件
         1,current refresh age 需要设置成 any,这是session级别,你也可以设置全局的DB参数 DFT_REFRESH_AGE。值是0的时候代表优化器不会选择使用MQT,这个参数代表用户对数据新旧的容忍度。
         2, 基表、MQT 及其索引的当前统计信息

         MQT的类型
         1,系统维护
          及时刷新
          延迟刷新(全量刷新)
          延迟刷新(增量刷新 staging表)
          2,用户维护
         
          系统维护和用户维护的区别:
          系统维护的MQT不允许进行增删改操作,可以通过refresh table 来收集base表的变更,从而updateMQT。而用户维护的MQT不同,你可以对MQT进行增删改操作,但不可以refresh table。用户需要自己向表中导入数据,自己来管理MQT。一般用户维护的MQT用的少。需要注意的是,当数据量比较大,第一次refresh table可能消耗资源大的时候,你可以通过cursor load数据到MQT,这在系统维护的MQT中是允许的。

         系统维护MQT的类型以及用法(结合explain来理解)
         1,及时刷新(refresh immediate)
         在你操作base表的同时,DB2会自动对相应的MQT进行操作(不需要refresh table)。
         优点:能保证数据的实时性,
         缺点:像索引那样影响性能,因为你需要同时对MQT表进行操作,占用disk
         建议:重要的需要及时更新的数据上面使用
         2, 延迟刷新
         在你操作base表的同时,DB2不会同时操作MQT表,只有当你refresh table的时候,才会对update MQT。
         优点:没有降低增删改的性能
         缺点:失去了数据的实时性,如果没有及时的refresh table,用户得到的数据可能是旧的。
         建议:用户对数据的及时性有一定容忍程度的数据,很少进行update,只读的数据可以用
      3,延迟刷新(增量刷新 staging表)
      在你操作base表的同时,DB2会操作MQT的stage表,当你refresh table的时候,通过staging表去update MQT。
      优点:可以取到某段时间的增量数据,而不需要重头刷新MQT。
                   refresh table的时候不需要用到base表。
                   DISK占用率小于其他两种方式,在refresh之后,staging表会被清空。
      缺点:失去了数据的实时性,如果没有及时的refresh table,用户得到的数据可能是旧的。
      建议:只需要数据的增量,而不是全部。
   
       及时刷新比延迟刷新的创建rule要严格很多,比如在你创建及时MQT的时候,你必须保证每个sum的列,都要有count的列,还需要有count(*),否则会创建失败。原因是当你delete or insert from base表的时候,DB2通过count字段快速判断是否有变化,而不需走表扫描。

      MQT的匹配原理(优化器什么时候会选择使用MQT)
      1,精确匹配
          也就是你创建的MQT和你查询的MQT是一模一样的,优化器会去用这个MQT。但也不是唯一的。在我做的实验当中,也有报"MQT too more expensive",最终访问计划放弃使用MQT的情况。我通过两种方法解决了这个问题,一是把MQT设置成immediate,二是保持deferred,减少group by使用的字段。
      2,子集匹配
          查询sql的结果集是MQT的子集。比如你在谓词部分加入column>1000,这种情况也能利用到MQT。
      3,查询中连接的表数目多于MQT
          相当于MQT是某个查询的一部分,但要保证这一部分并没有被过滤掉某些结果集,否则无法匹配。
      4,子集匹配,满足RI(引用完整性)
         MQT中的join表多于查询表,查询表是不会利用这个MQT的,因为join操作会影响MQT中表的行数,但如果额外的join操作是基于RI,也就是外表(=的是外键)。这个MQT是可以被利用的。
      5,函数依赖匹配
         查询表中包含MQT中没有的列,但此列是函数依赖于MQT中的列,这种情况也是能够用到MQT的。

         关于可否直接使用MQT的讨论:
      在使用一些比较复杂的表连接(里面有view,有union,有join之类的),创建MQT成功的时候会有warning信息,优化器可能不会使用此MQT。结果对一模一样的做模板的sql做了下explain,提示我MQT里面有view这些sql结构,优化器不使用MQT。听weiruan兄说oracle里面可以直接select MQT表,性能优于原始语句。前提是你要refresh table。在V7之前DB2里面有总结表(AST),估计也是这样的用法。至于是否refresh table的时间要比使用原始语句的效率要快,oracle我不敢说,DB2方面,从访问计划来看,直接使用MQT的sql语句,cost消耗要少很多,但这是在我refresh table的前提上。于是对refresh table时候做了explain,惊奇的发现refresh的时候,DB2自己会重新执行一遍原始sql,然后与MQT进行差分最后更新MQT。原来消耗是在这步了。于是我得到的结论是除非你使用的那些base表是只读的(不去refresh),否则使用MQT对性能提升几乎是负的(MQT表也需要维护),至少MQT在这方面的使用不是很理想。如果有使用经验的人可以分享下。
页: [1]
查看完整版本: 关于MQT的用法【转】