2009-06-22 3 views
9

У меня есть таблица из 5 651 744 строк с первичным ключом из 6 столбцов (int x 3, smallint, varchar (39), varchar (2)). Я хочу улучшить производительность с помощью этой таблицы и другой таблицы, которая разделяет этот первичный ключ плюс дополнительный добавленный столбец, но имеет 37-метровые строки.Столкновения CHECKSUM() в SQL Server 2005

В ожидании добавления столбца для создания хэш-ключа я сделал анализ и нашел 18,733 столкновений.

SELECT SUM(CT) 
FROM (
     SELECT HASH_KEY 
       ,COUNT(*) AS CT 
     FROM (
       SELECT CHECKSUM(DATA_DT_ID, BANK_NUM, COST_CTR_NUM, 
           GL_ACCT_NUM, ACCT_NUM, APPN_CD) AS HASH_KEY 
       FROM CUST_ACCT_PRFTBLT 
       ) AS X 
     GROUP BY HASH_KEY 
     HAVING COUNT(*) > 1 
     ) AS Y 

SELECT COUNT(*) 
FROM CUST_ACCT_PRFTBLT 

Это примерно в два раза хуже с BINARY_CHECKSUM()

ли это кажется слишком высокой (+0,33%), учитывая меньший относительный объем пространства назначения я покрывающей? И если коллизии настолько высоки, есть ли преимущество в объединении на этом изготовленном ключе сначала в соединениях для стоимости дополнительных 4 байтов в строке, учитывая, что вам все равно придется присоединяться к регулярным столбцам для обработки случайного столкновения?

+0

Сколько записей вы принимаете за один раз? Имеется ли таблица подробностей с кластеризованным индексом? Насколько широк? Если кластеризованный индекс является широким (т. Е. Включает все FK), можете ли вы его сбросить или заменить на столбец идентификатора? –

+0

Почему это проблема для вас? Что вам нужно сделать? –

+0

Проблема заключается в том, что у меня есть 200-миллиметровые строки производной статистики для создания из 37-метровых строк статистики, а PIVOT для выполнения вычислений должен поворачиваться на очень большом ключе, что привело к неприятной очереди на все 37-метровые строки в tempdb. –

ответ

7

Я не вижу, где добавление контрольной суммы получит вам что-нибудь с этим уровнем collisons. Даже 1 столкновение слишком велико, так как это приведет к тому, что вы присоединитесь к неправильным данным. Если вы не можете гарантировать, что присоединяетесь к правильной записи, бессмысленно, если оно улучшает производительность, но беспорядок с целостностью данных. Это, по-видимому, финансовые данные, поэтому вам лучше быть уверенным, что ваши запросы не приведут к плохим результатам. Фактически вы можете в конечном итоге списать или зачислить неправильные учетные записи, если есть какие-либо столкновения.

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

Вы считали использование суррогатного ключа, а затем уникальным индексом на шести натуральных ключевых полях? Затем вы можете присоединиться к суррогатной клавише и, вероятно, улучшить производительность. Невозможно эффективно объединить шесть столбцов (один из варчаров) вместо одного суррогатного ключа. Я понимаю, по размеру данных, это может быть сложнее реорганизовать, чем в непроизводственной системе, но на самом деле, возможно, стоит потратить время на постоянное устранение постоянных проблем с производительностью. Только вы можете сказать, насколько сложным было бы это изменение и насколько сложно было бы изменить все sps или запросы для лучшего соединения. Тем не менее, можно попробовать.

+0

Мне нужно было бы присоединиться к surrgate и всем столбцам PK. Суррогат должен быть первым столбцом в индексе (который оптимизатор, мы надеемся, выберет), но ВСЕ столбцы должны быть объединены. В этой документации MSDN есть пример (просто поиск, а не соединение): http://msdn.microsoft.com/en-us/library/ms189788(SQL.90).aspx –

+0

Зачем нужно присоединяться к суррогатный ключ и естественные первичные ключевые столбцы? Суррогатный ключ должен быть добавлен в обе таблицы, но вы будете использовать его вместо 6 полей, которые вы сейчас используете в соединении. – LanceSc

+0

Я вижу, настоящий уникальный суррогат, а не только хэш. Ну, к сожалению, унаследованная система, которую я реинжиниринг, не имеет RI, поэтому в таблице статистики строк 37m есть записи, которые не имеют записи в таблице PK строки 5m. Мне нужно подумать об этом. –

2

Если ваша контрольная сумма упадет до 0,33% данных, я бы сказал, что он работает нормально ... особенно если вы используете этот столбец в сочетании с другими (проиндексированными) столбцами.

Конечно, чтобы быть эффективным как индекс, который вы, вероятно, хотите вычислить и сохранить это значение при вставке/обновлении данных, с некластеризованным индексом.

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

+0

Да, я планировал использовать постоянный вычисленный столбец. –

1

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

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

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

Поскольку некластеризованный индекс будет содержать ключи кластеризации или указатель кучи, вы хотите: a) небольшой ключ кластеризации (например, столбец идентификатора int - 4 байтовый указатель) или b) не кластеризованный индекс вообще (8-байтовый указатель).

Если ваши запросы не являются выборочными, или если индекс кластеризации таблицы строк огромен (вся таблица минус несколько столбцов), то я не знаю, поможет ли контрольная сумма (возможно, более быстрая указательная навигация, возможно?). В любом случае вы хотели бы сделать его кластеризованным или охватывающим индексом, и если таблица заголовков сначала не кластеризуется в контрольной сумме, будет много сортировки.

Если вы можете позволить себе расходы на хранение и индексирование, возможно, будет несколько указателей на заголовок - заголовок и детализация.

1

Если ваш PRIMARY KEY сгруппирован, то каждый созданный вами индекс будет содержать это PRIMARY KEY.

Соединение на хеширован значение будет использовать эти следующие шаги:

  1. Найдите значение хэш-индекса ключа
    • Найдите значение PRIMARY KEY в индексных данных
    • Использование Clustered Index Seek определить местонахождение PRIMARY KEY строка в таблице

Присоединение к PRIMARY KEY будет использовать только шаг 3.

SQL Server, однако, достаточно умен, чтобы принять это во внимание, и если вы присоединитесь, как это:

SELECT * 
FROM main_table mt 
JOIN CUST_ACCT_PRFTBLT cap 
ON  cap.HASH_KEY = mt.HASH_KEY 
     AND cap.DATA_DT_ID = mt.DATA_DT_ID 
     AND … 
WHERE mt.some_col = @filter_value 

, он просто не будет использовать индекс на HASH_KEY, вместо этого, он будет использовать один Clustered Index Seek и Filter, чтобы убедиться, что значения хэша совпадают (и они всегда будут).

Резюме: просто присоединитесь к PRIMARY KEY.

Используя вторичный индекс, вам сначала нужно будет сделать бесполезный поиск HASH_KEY, а затем еще нужно присоединиться к PRIMARY KEY.

+0

Да, я избегал слишком масштабной реструктуризации этого процесса во время этой реорганизации, но поскольку ПК настолько широк (и кластеризован), я думаю, что я мог бы извлечь его и вместо этого использовать суррогат. В этом случае хэш не имеет значения. Моя основная проблема заключается в том, что в CUST_ACCT_STAT заканчиваются строки, которые не имеют соответствующего PK в CUST_ACCT_PRFTBLT из-за плохого RI в исходной системе, поэтому мне также нужно будет вывести строки для них. –

6

То, что я видел много людей, замалчивающих до сих пор, состоит в том, что CHECKSUM имеет тонну столкновений, на Microsoft's own admission. Это даже хуже, чем MD5, что имеет свою долю значимых столкновений.

Если вы хотите получить хеш-столбец, рассмотрите использование HASHBYTES с указанным SHA1. SHA1 имеет гораздо менее значимые столкновения, чем MD5 или CHECKSUM. Поэтому CHECKSUM никогда не следует использовать, чтобы определить, является ли строка уникальной, а скорее, это быстрая проверка верности двух значений.Следовательно, ваша скорость столкновения должна быть 0% с HASHBYTES, если у вас нет повторяющихся строк (которые, будучи ПК, никогда не должны происходить).

Имейте в виду, что HASHBYTES усечет все, что превышает 8000 байт, но ваш ПК намного меньше этого (все конкатенированные), поэтому у вас не должно быть никаких проблем.

+1

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

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

  • Нет связанных вопросов^_^