Разделение данных в таблице хранилища данных SQL Azure

Я пытаюсь немного разобраться с секционированными таблицами в хранилище данных SQL Azure. Но я вижу вещи, которые не имеют для меня смысла. Я явно делаю что-то не так, но не могу понять, в чем дело.

Я намерен заполнить первую таблицу (Marc.foo) 10000 строками данных, изучить метаданные разделения, а затем ПЕРЕКЛЮЧИТЬ раздел на вторую, пустую таблицу (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

Затем я заполняю первую таблицу (Marc.foo) 10000 строками:

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

Я ожидаю, что когда я SELECT из Marc.foo2, я увижу 1000 строк со значениями id от 1 до 1000. Но я верну нулевые строки.

Вопрос 2: Что я сделал не так?


person Marc Jellinek    schedule 19.04.2017    source источник


Ответы (2)


В вашем коде есть ошибка. Ваш CTE возвращает номер 1 для всех строк, что вы можете подтвердить, проверив содержимое таблицы #numbers. Таким образом, ваши критерии для id <= 10000 не действуют, и оператор всегда возвращает 65 536 строк:

1 1 1 1 1

Исправьте это, переместив 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

Я предполагаю, что мораль этой истории в том, что не пишите свою собственную процедуру генерации чисел, не проверив ее :)

person wBob    schedule 19.04.2017

Таблицы чисел в сторону, вот в чем проблема

Вопрос 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

Я ожидаю, что когда я SELECT из 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)))

Это означает, что строки с идентификатором до нуля, но не включая ноль, будут в разделе 1, строки с идентификатором от 0 до 999 будут в разделе 2.

В разделе 1 не было строк. Все работало так, как задумано. Если я переключил раздел 2, строки появятся в Marc.foo2.

person Marc Jellinek    schedule 20.04.2017