zoukankan      html  css  js  c++  java
  • 分区管理

    对表分区,对数据库有很多好处,通常来说,分区的好处有两个:减少产生死锁的竞争条件,和删除分区的数据。由于分区之间是相互独立的,因此,对一个分区加X锁,不会对其他分区产生竞争,这是避免死锁(dead lock)的一种方式。对大数据表进行数据删除操作时,可以使用分区切换,使用少量的IO,从分区表中删除海量的数据。

    在实际的项目中,有如下的分区函数和分区架构( Partition Scheme):

    CREATE PARTITION FUNCTION [funcPartition_int_DataSourceID](int) 
    AS RANGE LEFT 
    FOR VALUES (1, 2, 3)
    
    CREATE PARTITION SCHEME [schePartition_int_DataSourceID] 
    AS PARTITION [funcPartition_DataSourceID] 
    TO ([PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY])
    
    
    create table dbo.dt_test
    (
    ...More column definition
    
    DataSourceID int
    )
    on [schePartition_int_DataSourceID](DataSourceID)
    View Code

    一,减少产生死锁的竞争条件

    查看ETL的执行日志,日志中记录Package执行的消息,某些Package会因为发送死锁,作为死锁牺牲品(victim)而失败。查看这些Package,发现产生死锁的根本原因是:不同的Package同时更新同一张表,导致竞争,产生死循环而发生死锁。深入分析发生死锁的TSQL脚本,两个Package都使用 DataSourceID 作为过滤条件。推测,可能的原因是这两个DataSourceID位于同一个分区:

    1,验证边界值

    分区函数设置的边界值是执行分区的依据,验证边界值,能够确定分区列是否处于相同的分区中:

    select prv.function_id,pf.name,pf.boundary_value_on_right,prv.value as BoundaryValue
    from sys.partition_range_values prv
    inner join sys.partition_functions pf
        on prv.function_id=pf.function_id
    where pf.name='funcPartition_int_DataSourceID'

    边界值小于当前 DataSourceID的最大值,因此,产生竞争的两个DataSourceID 都是在最右边的分区中。缺少分区的管理计划,这会导致额外增加的分区列(DataSourceID)都被分配到同一个分区中。

    2,管理分区计划

    对表表去,不仅要有效地避免死锁,减少产生死锁的竞争条件,还要在删除大表数据时,使用少量IO实现海量数据的移动,通过分区切换(switch)和数据表截断(truncate),快速删除数据。分区切换是把整个分区切换到零时表中,这就要求,该分区列必须足够小,能够全部删除。管理分区计划的最佳实践,合理选择分区列,并预留空分区。

    如果一个分区是非空的,那么分区拆分(split range)会导致数据的移动,这可能是一个非常耗费IO的一个操作,为了避免密集的数据移动,最好是预留一个空的分区,一般是最右边的分区,该分区号最大,每次都把最右边的分区拆分成两个分区:

    declare @CurrentMaxBoundaryValue int
    declare @ExistingMaxDataSourceID int
    declare @BoudaryValue int
    declare @sql_prefix nvarchar(max)
    declare @sql nvarchar(max)
    
    set @sql_prefix=N'
    alter partition scheme [schePartition_int_DataSourceID]
    next used [primary]
    alter partition function [funcPartition_int_DataSourceID]()
    split range ('
    
    select @ExistingMaxDataSourceID = max(ds.DataSourceID)
    from dbo.dt_DataSource ds with(nolock)
    
    select @CurrentMaxBoundaryValue= max(cast(prv.value as int))
    from sys.partition_functions pf 
    inner join sys.partition_range_values prv
        on pf.function_id=prv.function_id
    where pf.name='funcPartition_int_DataSourceID'
    
    -- add new boundary value
    if @CurrentMaxBoundaryValue<@ExistingMaxDataSourceID+1
    begin
        set @BoudaryValue=@CurrentMaxBoundaryValue+1
    
        while @BoudaryValue<=@ExistingMaxDataSourceID+1
        begin   
            select @sql = @sql_prefix+ cast(@BoudaryValue as varchar(10))+ N')'
            exec(@sql)
    
            set @BoudaryValue=@BoudaryValue+1
        end
    end
    View Code

    二,可能出现的错误

    1,SET选项错误

    在执行分区脚本对索引进行分区的,可能会遇到SET选项错误,根据错误消息,启用想用的SET选项:

    UNKNOWN TOKEN failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations. [SQLSTATE 42000] (Error 1934).  

    上述消息表面当前数据库的QUOTED_IDENTIFIER设置错误,使用SET命令启用QUOTED_IDENTIFIER选项:

    SET QUOTED_IDENTIFIER  ON

    参考文档:

    SET QUOTED_IDENTIFIER (Transact-SQL)

  • 相关阅读:
    6 全局锁和表锁
    oracle ogg--ogg搭建过程中遇到的错误及处理
    5 深入浅出索引(下)
    4 深入浅出索引(上)
    oracle ogg 单实例双向-新增表,修改表结构(oracle-oracle
    oracle ogg 单实例双向复制搭建(oracle-oracle)--Oracle GoldenGate
    Iview 中 获取 Menu 导航菜单 选中的值
    idea中git分支的使用
    vue使用axios进行ajax请求
    web前端_Vue框架_设置浏览器上方的标题和图标
  • 原文地址:https://www.cnblogs.com/ljhdo/p/5070031.html
Copyright © 2011-2022 走看看