【问题标题】:Partition data within an Azure SQL Data Warehouse tableAzure SQL 数据仓库表中的分区数据
【发布时间】:2017-04-19 18:16:35
【问题描述】:

我正在尝试使用 Azure SQL 数据仓库中的分区表。但我看到的东西对我来说没有意义。我显然做错了什么,但我无法弄清楚它是什么。

我的意图是用 10000 行数据填充第一个表 (Marc.foo),检查分区元数据,然后将分区切换到第二个空表 (Marc.foo2)。

我从创建两个分区表开始:

IF OBJECT_ID('Marc.foo', 'U') IS NOT NULL
  DROP TABLE Marc.foo
GO

IF OBJECT_ID('Marc.foo2', 'U') IS NOT NULL
  DROP TABLE Marc.foo2
GO

CREATE TABLE Marc.foo
(
    id int NOT NULL
)
WITH 
(   
     DISTRIBUTION = HASH (id),
     CLUSTERED COLUMNSTORE INDEX, 
     PARTITION (id RANGE RIGHT FOR VALUES (0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000))
)
GO

CREATE TABLE Marc.foo2
(
    id int NOT NULL
)
WITH 
(   
     DISTRIBUTION = HASH (id),
     CLUSTERED COLUMNSTORE INDEX, 
     PARTITION (id RANGE RIGHT FOR VALUES (0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000))
)
GO

然后我用 10000 行填充第一个表 (Marc.foo):

IF OBJECT_ID('tempdb..#numbers', 'U') IS NOT NULL
  DROP TABLE #numbers
GO

WITH 
    CTE_2 AS (SELECT 1 as id UNION ALL SELECT 1 as id), 
    CTE_4 AS (SELECT a.id FROM CTE_2 a, CTE_2 b), 
    CTE_16 AS (SELECT a.id FROM CTE_4 a, CTE_4 b), 
    CTE_256 AS (SELECT a.id FROM CTE_16 a, CTE_16 b), 
    CTE_64K AS (SELECT a.id FROM CTE_256 a, CTE_256 b)
SELECT      id
INTO        #numbers
FROM        CTE_64K

INSERT INTO Marc.foo(id)
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM #numbers WHERE id <=10000

因为我刚刚将数据加载到表中,所以我要在表上创建统计信息:

CREATE STATISTICS stats_Marc_foo_id ON Marc.foo(id) WITH FULLSCAN

现在我检查分区元数据:

SELECT      sch.name AS [schema_name],
            tbl.[name] AS [table_name],
            ds.type_desc, 
            prt.[partition_number],
            rng.[value] AS [current_partition_range_boundary_value],
            prt.[rows] AS [partition_rows]
FROM        sys.schemas                             sch
            INNER JOIN sys.tables                   tbl ON  sch.schema_id       = tbl.schema_id
            INNER JOIN sys.partitions               prt ON  prt.[object_id]     = tbl.[object_id]
            INNER JOIN sys.indexes                  idx ON  prt.[object_id]     = idx.[object_id] AND prt.[index_id] = idx.[index_id]
            INNER JOIN sys.data_spaces              ds  ON  idx.[data_space_id] = ds.[data_space_id]
            INNER JOIN sys.partition_schemes        ps  ON  ds.[data_space_id]  = ps.[data_space_id]
            INNER JOIN sys.partition_functions      pf  ON  ps.[function_id]    = pf.[function_id]
            LEFT JOIN sys.partition_range_values    rng ON  pf.[function_id]    = rng.[function_id] AND rng.[boundary_id] = prt.[partition_number]
WHERE       sch.name = 'Marc' AND
            tbl.name = 'foo'

问题 1:这给出了我对 current_partition_range_boundary_value 的预期,但 partition_rows(我预计为 1000)为每个分区返回 5957 行。

最后,我尝试将分区 1 从 Marc.foo 切换到 Marc.foo2

ALTER TABLE Marc.foo SWITCH PARTITION 1 to Marc.foo2 PARTITION 1

我希望当我从 Marc.foo2 中选择时,我应该看到 1000 行,id 值从 1 到 1000。但我得到了零行。

问题 2:我做错了什么?

【问题讨论】:

    标签: sql-server azure-sqldw


    【解决方案1】:

    您的代码中有错误。您的 CTE 为所有行返回数字 1,您可以通过检查 #numbers 表的内容来确认。因此,id &lt;= 10000 的标准无效,并且该语句总是带回 65,536 行:

    通过将您的 ROW_NUMBER 向上移动到 SELECT ... INTO 来更正此问题,例如

    WITH 
        CTE_2 AS (SELECT 1 as id UNION ALL SELECT 1 as id), 
        CTE_4 AS (SELECT a.id FROM CTE_2 a, CTE_2 b), 
        CTE_16 AS (SELECT a.id FROM CTE_4 a, CTE_4 b), 
        CTE_256 AS (SELECT a.id FROM CTE_16 a, CTE_16 b), 
        CTE_64K AS (SELECT a.id FROM CTE_256 a, CTE_256 b)
    SELECT      ROW_NUMBER() OVER (ORDER BY (SELECT NULL))  AS id
    INTO        #numbers
    FROM        CTE_64K
    

    我猜这个故事的寓意是,不要在没有检查的情况下编写自己的数字生成例程:)

    【讨论】:

      【解决方案2】:

      除了数字表,问题来了

      问题 1:这给出了我期望的 current_partition_range_boundary_value,但 partition_rows(我期望为 1000)为每个分区返回 5957 行。

      我仍然无法得到我期望的答案。

      最后,我尝试将分区 1 从 Marc.foo 切换到 Marc.foo2

      ALTER TABLE Marc.foo SWITCH PARTITION 1 to Marc.foo2 PARTITION 1
      

      我希望当我从 Marc.foo2 中选择时,我应该看到 1000 行,id 值从 1 到 1000。但我得到了零行。

      问题 2:我做错了什么?

      我误解了RANGE RIGHT。如果我们查看 CREATE TABLE 的分区子句,我们会看到:

      PARTITION (id RANGE RIGHT FOR VALUES (0, 1000, 2000, 3000, 4000, 5000, 
      6000, 7000, 8000, 9000)))
      

      这意味着 ID 不超过 0 的行将在分区 1 中,ID 介于 0 和 999 之间的行将在分区 2 中。

      分区 1 中没有行。这是按设计工作的。如果我切换分区 2,行会出现在 Marc.foo2

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-30
        • 1970-01-01
        • 1970-01-01
        • 2018-05-04
        • 2020-05-28
        • 2016-10-26
        • 2021-03-04
        • 1970-01-01
        相关资源
        最近更新 更多