AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 186420
Accepted
Peter
Peter
Asked: 2017-09-21 03:52:54 +0800 CST2017-09-21 03:52:54 +0800 CST 2017-09-21 03:52:54 +0800 CST

分区表上的离线索引重建

  • 772

如果我使用ntext,text或image数据类型对表进行分区,并使用 重建单个分区上的索引online = off,是锁定整个表还是仅锁定相关分区?

sql-server sql-server-2016
  • 1 1 个回答
  • 1141 Views

1 个回答

  • Voted
  1. Best Answer
    Erik Darling
    2017-10-01T07:26:05+08:002017-10-01T07:26:05+08:00

    我花了一些时间看这个,因为我已经写了一些演示脚本,所以很容易检查其余部分。让我们进行设置,然后查看结果。这将创建必要的分区表和索引。

    CREATE PARTITION FUNCTION YourMom ( INT )
        AS RANGE LEFT FOR VALUES ( 1000000, 2000000, 3000000, 4000000, 5000000 );
    
    CREATE PARTITION SCHEME YourDad
        AS PARTITION YourMom
        ALL TO ( [PRIMARY] );
    
    CREATE TABLE dbo.YourAuntDebbie
    (
        Id INT,
        StopUsingDeprecatedDataTypes NTEXT
    ) ON YourDad (Id);
    
    
    DECLARE @counter INT = 1;
    WHILE @counter < 6
        BEGIN
    
            RAISERROR('Run number: %d', 0, 1, @counter) WITH NOWAIT;
    
            INSERT dbo.YourAuntDebbie WITH ( TABLOCK ) ( Id, StopUsingDeprecatedDataTypes )
            SELECT TOP 1000000 x.n + CASE WHEN @counter = 1 THEN 0
                                          WHEN @counter = 2 THEN 1000000 
                                          WHEN @counter = 3 THEN 2000000 
                                          WHEN @counter = 4 THEN 3000000 
                                          WHEN @counter = 5 THEN 4000000 
                                          ELSE 0 
                                          END, 
                               REPLICATE(N'A', x.n % 10000)
            FROM   (   SELECT ROW_NUMBER() OVER ( ORDER BY @@ROWCOUNT ) AS n
                       FROM   sys.messages AS m
                       CROSS JOIN sys.messages AS m2 ) AS x;
    
            SET @counter += 1;
    
        END;
    
    CREATE CLUSTERED INDEX ix_whatever
        ON dbo.YourAuntDebbie ( Id ) ON YourDad(Id);
    

    这给了我 5 个具有 100 万行的分区和一个空分区。

    SELECT OBJECT_NAME(p.object_id) AS table_name, p.partition_number, p.rows
    FROM   sys.partitions AS p
    WHERE  p.object_id = OBJECT_ID('dbo.YourAuntDebbie');
    

    花式表:

    +----------------+------------------+---------+
    |   table_name   | partition_number |  rows   |
    +----------------+------------------+---------+
    | YourAuntDebbie |                1 | 1000000 |
    | YourAuntDebbie |                2 | 1000000 |
    | YourAuntDebbie |                3 | 1000000 |
    | YourAuntDebbie |                4 | 1000000 |
    | YourAuntDebbie |                5 | 1000000 |
    | YourAuntDebbie |                6 |       0 |
    +----------------+------------------+---------+
    

    这是我用来查看索引重建需要哪些锁的 XE 会话:

    CREATE EVENT SESSION Locks
        ON SERVER
        ADD EVENT sqlserver.lock_acquired
        ( SET collect_resource_description = ( 1 )
         ACTION ( sqlserver.sql_text )
         WHERE (   sqlserver.equal_i_sql_unicode_string(sqlserver.database_name, N'Crap')
                   AND package0.equal_uint64(sqlserver.session_id, ( 61 )))),
        ADD EVENT sqlserver.lock_released
        ( SET collect_resource_description = ( 1 )
         ACTION ( sqlserver.sql_text )
         WHERE (   sqlserver.database_name = N'Crap'
                   AND sqlserver.session_id = ( 61 )))
        ADD TARGET package0.event_file
        ( SET filename = N'c:\temp\Locks' )
        WITH ( MAX_MEMORY = 4096KB,
               EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS,
               MAX_DISPATCH_LATENCY = 30 SECONDS,
               MAX_EVENT_SIZE = 0KB,
               MEMORY_PARTITION_MODE = NONE,
               TRACK_CAUSALITY = ON,
               STARTUP_STATE = OFF );
    GO
    

    有了它,我可以重建我的分区,然后深入研究 XE。

    ALTER EVENT SESSION Locks ON SERVER STATE = START;
    
    ALTER INDEX ix_whatever ON dbo.YourAuntDebbie REBUILD PARTITION = 1 WITH (ONLINE = OFF);
    GO 
    
    ALTER INDEX ix_whatever ON dbo.YourAuntDebbie REBUILD PARTITION = 2 WITH (ONLINE = OFF);
    GO 
    
    ALTER INDEX ix_whatever ON dbo.YourAuntDebbie REBUILD PARTITION = 3 WITH (ONLINE = OFF);
    GO 
    
    ALTER INDEX ix_whatever ON dbo.YourAuntDebbie REBUILD PARTITION = 4 WITH (ONLINE = OFF);
    GO 
    
    ALTER INDEX ix_whatever ON dbo.YourAuntDebbie REBUILD PARTITION = 5 WITH (ONLINE = OFF); 
    GO 
    
    ALTER INDEX ix_whatever ON dbo.YourAuntDebbie REBUILD PARTITION = 6 WITH (ONLINE = OFF);
    GO 
    
    ALTER EVENT SESSION Locks ON SERVER STATE = STOP;
    

    现在,我要把 XE 事件粉碎的东西放在最后,因为它非常丑陋,没有理由让每个人都坐下来看结果。我将使用第一个分区的结果作为示例,但它们在所有 6 个分区中几乎相同,即使是空分区也是如此。

    我将更新结果限制为仅对象级锁。这些是我们唯一关心的。

       +---------------+-------------------------+----------------+--------------+-------+------------------+--------+
    |   EventName   |        EventDate        |   ObjectName   | ResourceType | Mode  | PARTITIONREBUILT | Events |
    +---------------+-------------------------+----------------+--------------+-------+------------------+--------+
    | lock_acquired | 2017-10-03 13:21:14.554 | YourAuntDebbie | OBJECT       | SCH_M | PARTITION = 1    |      1 |
    | lock_acquired | 2017-10-03 13:21:14.554 | YourAuntDebbie | OBJECT       | SCH_S | PARTITION = 1    |      1 |
    | lock_released | 2017-10-03 13:21:14.554 | YourAuntDebbie | OBJECT       | SCH_S | PARTITION = 1    |      1 |
    | lock_acquired | 2017-10-03 13:21:14.603 | YourAuntDebbie | OBJECT       | S     | PARTITION = 1    |      6 |
    | lock_acquired | 2017-10-03 13:21:14.603 | YourAuntDebbie | OBJECT       | SCH_S | PARTITION = 1    |     30 |
    | lock_released | 2017-10-03 13:21:14.603 | YourAuntDebbie | OBJECT       | SCH_S | PARTITION = 1    |     24 |
    | lock_released | 2017-10-03 13:21:14.867 | YourAuntDebbie | OBJECT       | SCH_M | PARTITION = 1    |      1 |
    +---------------+-------------------------+----------------+--------------+-------+------------------+--------+
    

    据我所知,对于每个分区SCH-M,在索引重建开始时取出一个锁,并在THE TABLE结束时释放。

    例如,如果我在事务中运行单个分区重建:

    BEGIN TRAN
    
    ALTER INDEX ix_whatever ON dbo.YourAuntDebbie REBUILD PARTITION = 1 WITH (ONLINE = OFF);
    
    --ROLLBACK
    

    然后在另一个 SSMS 窗口中:

    SELECT *
    FROM dbo.YourAuntDebbie AS yad
    WHERE yad.Id = 6000000
    AND 1 = (SELECT 1)
    

    选择被阻止,直到我终止重建。完成后,查询计划显示正在消除分区,因此只有正在重建的分区 1 似乎会影响整个表。

    坚果

    希望这可以帮助!

    现在这是可怕的 XE 会话粉碎代码:

        CREATE TABLE #Locks
           (
             ID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY CLUSTERED,
             WaitsXML XML 
           );
    
    INSERT  #Locks
            ( WaitsXML )
    SELECT    CONVERT(XML, event_data) AS TargetData
    FROM      sys.fn_xe_file_target_read_file( 'c:\temp\Locks*.xel', NULL, NULL, NULL);
    
    WITH locks
    AS ( SELECT l.WaitsXML.value('(/event/@name)[1]', 'VARCHAR(128)') AS EventName,
                l.WaitsXML.value('(/event/@timestamp)[1]', 'DATETIME2(3)') AS EventDate,
                l.WaitsXML.value('(event/data[@name="object_id"]/value)[1]', 'NUMERIC') AS ObjectId,
                l.WaitsXML.value('(event/data[@name="resource_type"]/text)[1]', 'VARCHAR(128)') AS ResourceType,
                l.WaitsXML.value('(event/data[@name="mode"]/text)[1]', 'VARCHAR(128)') AS Mode,
                l.WaitsXML.value('(event/action[@name="sql_text"]/value)[1]', 'VARCHAR(128)') AS SQLText,
                l.WaitsXML
         FROM   #Locks AS l )
    SELECT   locks.EventName,
             locks.EventDate,
             ISNULL(OBJECT_NAME(locks.ObjectId), 'Unknown') AS ObjectName,
             locks.ResourceType,
             locks.Mode,
             SUBSTRING(
                 locks.SQLText,
                 CHARINDEX('PARTITION', locks.SQLText),
                 CHARINDEX('WITH', locks.SQLText, CHARINDEX('PARTITION', locks.SQLText))
                 - CHARINDEX('PARTITION', locks.SQLText)) AS PARTITIONREBUILT,
             COUNT(*) AS Events
    FROM     locks
    WHERE    OBJECT_NAME(locks.ObjectId) = 'YourAuntDebbie'
             --OR OBJECT_NAME(locks.ObjectId) IS NULL
    GROUP BY ISNULL(OBJECT_NAME(locks.ObjectId), 'Unknown'),
             SUBSTRING(
                 locks.SQLText,
                 CHARINDEX('PARTITION', locks.SQLText),
                 CHARINDEX('WITH', locks.SQLText, CHARINDEX('PARTITION', locks.SQLText))
                 - CHARINDEX('PARTITION', locks.SQLText)),
             locks.EventName,
             locks.EventDate,
             locks.ResourceType,
             locks.Mode
    ORDER BY locks.EventDate;
    
    • 13

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve