2009-10-21 3 views
7

Это FACT Таблица в хранилище данныхИндексация Производительность BigInt против VarChar

Он имеет композитный индекс следующего

ALTER TABLE [dbo].[Fact_Data] 
ADD CONSTRAINT [PK_Fact_Data] 
PRIMARY KEY CLUSTERED 
(
    [Column1_VarChar_10] ASC, 
    [Column2_VarChar_10] ASC, 
    [Column3_Int] ASC, 
    [Column4_Int] ASC, 
    [Column5_VarChar_10] ASC, 
    [Column6_VarChar_10] ASC, 
    [Column7_DateTime] ASC, 
    [Column8_DateTime] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON 
) ON [PRIMARY] 
GO 

В этой структуре все из VARCHAR 10 колонка имеет только числовые значения. Будет ли полезно изменить эту 78-миллионную структуру строк для хранения BIGINT вместо VARCHAR с точки зрения запросов и индексирования?

Любые другие преимущества/недостатки, которые я должен учитывать?

ответ

14

Вы должны ОПРЕДЕЛЕННО ввести суррогат INT IDENTITY() первичный ключ !! INT уже дает вам потенциально до 2 миллиардов строк - этого недостаточно?

Этот ключ с ключом/кластером на SQL Server будет иметь размер до 64 байтов (вместо 4 для INT), что сделает ваш кластеризованный индекс и весь ваш некластеризованный индекс раздутым до неузнаваемости. Весь ключ кластеризации (все ваши 8 столбцов) будет включен на каждую страницу каждого отдельного некластеризованного индекса в этой таблице - для того, чтобы точно тратить много и много места.

Так что в любой индексной таблице вы должны иметь до 16 раз больше записей с суррогатным кластером INT, что означает, что у вас меньше ввода-вывода, меньше времени, затрачиваемого на чтение индексных страниц.

И представьте, что вы пытаетесь установить отношение внешнего ключа к этой таблице .... любая дочерняя таблица должна иметь все 8 столбцов вашего первичного ключа в качестве столбцов внешнего ключа и указать все 8 столбцов в каждом присоединяйтесь - какой кошмар!

У 78 миллионов строк, даже изменение ключа кластеризации на INT IDENTITY позволит вам сэкономить до 60 байт в строке - это само по себе будет составлять до 4 ГБ свободного места на диске (и использование ОЗУ на вашем сервере) , И это даже не начало подсчета сбережений по некластеризованным индексам .......

И, конечно же, да, я бы также изменил VARCHAR (10) на INT или BIGINT - если это число , сделайте тип поля числовым - не стоит оставлять его в VARCHAR (10), действительно. Но это само по себе не будет иметь большого значения с точки зрения скорости или производительности - это просто упрощает работу с данными (не обязательно всегда приворачивать к числовым типам, когда, например, сравнивает значения и т. Д.).

Марк

+1

это таблица фактов в моем хранилище данных. нет таблиц, использующих PK от этого как FK. –

+0

@ Raj: Ах, хорошо, это объясняет несколько вещей - вы забыли упомянуть об этом. Но все же: у вас есть и некластеризованные индексы на этой таблице? Это определенно сильно связано с наличием одного основного или кластерного ключа INT или BIGINT. –

+0

Bigint использует 64 бита, а не байты, т. Е. Он вдвое больше, а не 16 раз. – Yrlec

1

Марк S прав в том, что первичный ключ 64 байт будет дублироваться в каждом индексе NC, так что вы собираетесь заплатить стоимость ввода/вывода, которые будут влиять на объем данных, которые хранится в памяти (поскольку вы тратите пространство на индексной странице NC). Поэтому на этой основе вопрос заключается не в том, «должен ли я преобразовать свои varchars», а «следует ли мне преобразовать свой кластеризованный индекс в нечто совершенно иное».

Что касается varchar vs bigint, то есть хорошая причина для преобразования if вы можете позволить себе время; что за пределами 2-байтовой разницы в хранении на поле, когда вы сравниваете значения двух разных типов, SQL будет вынужден преобразовать один из них. Это будет происходить при каждом отдельном сравнении, будь то для соединения с индексом или предикате внутри предложения where.

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

4

Две вещи, которые могут повлиять на индекс (и общую БД) производительность:

1) Размер индексной странице скорости 2) Сравнение

Таким образом, для первого, в общем, чем меньше ваш индекс/данные страница, тем больше страниц вы можете хранить в памяти, и тем больше вероятность того, что данный запрос сможет найти страницу в кеше и медленном диске. Таким образом, вы хотите использовать наименьший тип данных, который может с комфортом соответствовать вашим существующим и предлагаемым будущим потребностям.

BigInt - 8 байт; VARCHAR может быть меньше, если размер данных невелик, поэтому он действительно зависит от ваших данных. Тем не менее, 10-символьные длинные числа могут быть в состоянии соответствовать типу данных SQL Server (http://msdn.microsoft.com/en-us/library/ms187745.aspx) в зависимости от размера, поэтому int vs. bigint зависит от вашего домена.

Кроме того, если вся ваша строка имеет фиксированную длину, некоторые определенные оптимизации SQL Server могут выполнять в сканировании, так как она точно знает, где на диске следующая строка (при условии, что строки смежны). Конечно, край, но это может помочь.

Для второго, быстрее сравнивать целые числа, чем строки Unicode. Итак, если вы только сохраняете числовые данные, вам определенно нужно переключиться на нужный размерный тип данных.

Наконец, Марк прав, что это становится очень запутанным первичным ключом. Однако, если ваши данные требуют этого - например, это ваши ТОЛЬКО столбцы, и вы никогда не делаете add'l-запросов, вы можете прекрасно настроить оптимизированную версию (с Bigints и т. Д.) Вашего основного ключа. Однако, как бы то ни было, запах кода, поэтому я повторю его совет, чтобы действительно взглянуть на вашу модель данных и посмотреть, правильно ли это.

Смежные вопросы