Разделение таблицы SQL Server на основе функции модуля? - PullRequest
5 голосов
/ 01 февраля 2010

У меня действительно большая таблица (более 10 миллионов строк), которая начинает демонстрировать признаки снижения производительности для запросов. Поскольку эта таблица, вероятно, удвоится или утроится по размеру относительно скоро, я собираюсь разбить таблицу на части, чтобы уменьшить производительность запросов.

Таблица выглядит примерно так:

CREATE TABLE [my_data] (
    [id] [int] IDENTITY(1,1) NOT NULL,
    [topic_id] [int] NULL,
    [data_value] [decimal](19, 5) NULL
)

Итак, куча значений для любой данной темы. Запросы к этой таблице всегда будут по идентификатору темы, поэтому есть кластерный индекс (id, topic_id).

В любом случае, поскольку идентификаторы тем не ограничены (можно добавить любое количество тем), я хотел бы попробовать разбить эту таблицу на функцию модуля идентификаторов тем. Так что-то вроде:

topic_id % 4 == 0 => partition 0
topic_id % 4 == 1 => partition 1
topic_id % 4 == 2 => partition 2
topic_id % 4 == 3 => partition 3

Однако я не видел никакого способа сказать «создать функцию раздела» или «создать схему раздела» для выполнения этой операции при выборе раздела.

Это вообще возможно? Как мы можем сделать функцию разделения на основе операции, выполняемой над входным значением?

Ответы [ 4 ]

5 голосов
/ 02 февраля 2010

Вам просто нужно создать свой столбец модуля в виде вычисляемого столбца PERSISTED.

Стиль Blue Peter, вот тот, который я сделал ранее (хотя я не уверен на 100%, что у меня есть правильное предложение для значений разделов):

CREATE PARTITION FUNCTION [PF_PartitonFour] (int)
AS RANGE RIGHT
FOR VALUES (
  0,
  1,
  2)
GO

CREATE PARTITION SCHEME [PS_PartitionFourScheme]
AS PARTITION [PF_PartitonFour]
TO ([TestPartitionGroup1],
    [TestPartitionGroup2],
    [TestPartitionGroup3],
    [TestPartitionGroup4])
GO

CREATE TABLE [my_data] (
  [id] [int] IDENTITY(1,1) NOT NULL,
  [topic_id] [int] NULL,
  [data_value] [decimal](19, 5) NULL
  [PartitionElement] AS [topic_id] % 4 PERSISTED,
) ON [PS_PartitionFourScheme] (PartitionElement);
GO
3 голосов
/ 01 февраля 2010

Хеш-разделение недоступно в SQL Server 2005/2008. Вы должны использовать разбиение диапазона.

При этом вам следует помнить, что разбиение - это в первую очередь опция хранения, см. Понятия секционированной таблицы и индекса :

Разделение делает большие таблицы или индексы более управляемы , потому что разделение позволяет вам управлять и быстрый доступ к подмножествам данных и эффективно, сохраняя при этом целостность сбора данных. От используя разбиение, операция такая как загрузка данных из OLTP в OLAP система занимает всего несколько секунд, вместо минут и часов операция принимает в более ранних версиях SQL Server. Техническое обслуживание Операции которые выполняются на подмножествах данных также выполняются более эффективно потому что эти операции предназначены только для данные, которые требуются, а не весь стол.

Как видите, введение в MSDN секционирования сосредоточено на обслуживании, управляемости и загрузке данных. По моему опыту, разбиение дает в лучшем случае 0 прирост производительности. Особенно в SQL 2005. Обычно это дает снижение производительности. Для повышения производительности следует использовать правильный кластеризованный индекс и правильно разработанные некластеризованные индексы.

В SQL 2008 есть улучшения в параллельных операторах в отношении разделов, если они правильно распределены с точки зрения ввода-вывода, см. Проектирование разделов для улучшения производительности запросов . Их преимущества незначительны и омрачены преимуществами правильно спроектированного набора кластеризованных и некластеризованных индексов. Например, кластерный индекс в (id, topic_id), где id - это идентификатор, полезен исключительно для поиска по одному элементу по id. С другой стороны, кластеризованный индекс (topic_id, id) будет полезен для любых запросов, которые ищут конкретные темы. Я не знаю ваши системные требования и запросы, которые вы выполняете, но проблемы с производительностью 10M строк в такой узкой таблице пахнут, как проблемы с индексированием и запросами, без проблем с разделами.

0 голосов
/ 02 февраля 2010

10 миллионов строк не так много для SQL-сервера;Обычный дизайн индекса, вероятно, решит эту проблему без необходимости разделения.Как уже было отмечено, попробуйте кластеризацию по разным наборам столбцов;кластеризация по topicid, id кажется чем-то, что нужно проверить, особенно если большинство запросов имеют topicid в качестве критерия.Подобный кластерный индекс имеет примерно тот же эффект, что и разделение, по крайней мере в том смысле, что он группирует связанные строки данных вместе на диске и позволяет сканировать диапазон для их быстрого извлечения.

Если этот проект работает, все, что вам нужнонадо беспокоиться о фрагментации от вставок, но это управляемо.После правильного индексирования убедитесь, что у вас достаточно оперативной памяти и нет узкого места на диске.

0 голосов
/ 01 февраля 2010

Из документации кажется, что вы должны указать значения для функции:

Чтобы создать 4 раздела ...

CREATE PARTITION FUNCTION myRangePF1 (int)
AS RANGE LEFT FOR VALUES (1, 100, 1000);

Не могли бы вы просто выполнить вычисления над этим вызовом и найти правильные значения для разделения? Подставить значения в вызов? Или я скучаю, почему вы хотите использовать модуль? Исходя из вероятности того, что в вашем идентификаторе есть пробелы, вам может потребоваться использовать статистические математические данные, чтобы определить, где разделить данные.

CREATE PARTITION FUNCTION myRangePF1 (int)
AS RANGE LEFT FOR VALUES (@low, @Med, @High);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...