Вычисление хэшей для строк в базе данных SQL Server - стоит усилий? - PullRequest
2 голосов
/ 31 марта 2009

Допустим, в моей базе данных SQL Server 2005 есть таблица из миллиона строк [mytable], в которой есть столбцы:

  • ID
  • SomeField
  • AnotherField
  • 1010 * Url *

Очень распространенный запрос в этой системе:

выберите * из [mytable], где url = 'http://www.somesite.com/some/really/long/url'

Что даст мне лучшую производительность:

a) Добавить индекс в столбец Url.

или

b) Добавьте дополнительный столбец «url_hash», который содержит числовой хеш, соответствующий URL, а затем вычислите этот хеш для использования в предложении «где», например ::

выберите * из [mytable], где url_hash = some-computed-hash и url = 'http://www.somesite.com/some/really/long/url'

Стоит ли (б) дополнительной сложности? Мне нужно вычислить хэш при вставке и выбрать.

ОБНОВЛЕНИЕ 03-30-2009

ID - это первичный ключ

Кроме того, запросы выше не должны иметь "*". Вместо этого в списке выбора должны быть все поля таблицы.

"*" было просто сокращением - извините за путаницу.

ОБНОВЛЕНИЕ 03-31-2009

Также, забыл упомянуть, в поле url_hash будет индекс.

Ответы [ 4 ]

4 голосов
/ 31 марта 2009

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

Но давайте сопоставим эту стоимость сравнения длинной строки со стоимостью их размещения на диске.

Индексы хранятся в деревьях B +, которые представляют собой сбалансированные деревья с переменным числом узлов и где каждый узел связан с другим (a -> b -> c). Это дает нам две возможности: быстрый поиск путем обхода дерева, а затем быстрый доступ в порядке дерева к другим узлам (как только вы найдете «a», легко найти «b», затем «c» и т. Д.).

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

Чем ниже высота, тем меньше попаданий на диск вы должны сделать. Если у вас есть дерево высотой 4, то для достижения любого случайного узла требуется загрузка 4 страниц индекса в ОЗУ, а это 4 обращения к диску. Таким образом, старшее дерево 4 "вдвое эффективнее" (для различных значений "удвоено"), чем старшее дерево 8.

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

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

Так вот, в этом и есть ценность иметь маленькие ключи - много поклонников в ваших индексных деревьях.

Имейте в виду, с хешем вам все равно придется делать "где хэш = и url = '...'".

Но это действительно сводится к вашим шаблонам доступа к данным, правда. Насколько занята БД, какие запросы вы делаете, сколько оперативной памяти у вас для кэширования страниц индекса и т. Д.

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

Ключевым выводом является то, что количество записей не имеет значения, но веер из дерева индексов имеет значение. Например, если у вас есть индексный узел 1 КБ и 4-байтовый индекс (длинное целое), вы можете получить 250 узлов на индекс (очень упрощенно), а трехслойное дерево может получить, что, 16 миллионов строк в пределах одного 3 глубоких дерева - любая из 16 миллионов строк в 3 попаданиях на диск.

4 голосов
/ 31 марта 2009

Если вы выберете только нужные вам столбцы (в отличие от '*') и создадите некластеризованный индекс покрытия для «Url» и выбранных столбцов, вы получите очень эффективный поиск.

0 голосов
/ 31 марта 2009

Описывает ли это реальную проблему, с которой вы сталкиваетесь в реальной таблице в реальном приложении, или вы ищете оптимизацию, которую еще не знаете, нужна ли она вам?

Если нет # 1, то я предлагаю вам проиндексировать URL и работать с остальной частью приложения, пока у вас не возникнет проблема (что вряд ли).

0 голосов
/ 31 марта 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...