Подтвердить что ты не робот

Лучший первичный ключ для хранения URL-адресов

который является лучшим первичным ключом для хранения адреса веб-сайта и URL-адресов страниц?

Чтобы избежать использования идентификатора autoincremental (который не привязан к данным), я разработал схему с использованием сигнатуры SHA1 URL-адреса в качестве первичного ключа.

Этот подход полезен во многих отношениях: например, мне не нужно читать last_id из базы данных, поэтому я могу подготовить все обновления таблицы, вычисляя ключ, и выполнять реальное обновление в одной транзакции. Отсутствие нарушения ограничений.

В любом случае я прочитал две книги, которые говорят мне, что я ошибаюсь. В "Высокопроизводительной MySQL" говорится, что случайный ключ не подходит для оптимизатора БД. Более того, в каждой книге Джо Селко он говорит, что первичный ключ должен быть частью данных.

Вопрос в том, что естественные ключи для URL-адресов... являются самими URL-адресами. Дело в том, что если для сайта коротко (www.something.com), там нет наложенного ограничения для am URL (см. http://www.boutell.com/newfaq/misc/urllength.html).

Считаю, что мне нужно хранить (и работать с) несколько миллионов из них.

Какой из них лучший ключ? Автоинкрементные идентификаторы, URL-адреса, хэши URL-адресов?

4b9b3361

Ответ 1

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

Что касается других столбцов и индексов, которые вы хотите, это зависит, как всегда, от того, как вы собираетесь их использовать.

Столбец, хранящий хэш каждого URL-адреса, является отличной идеей практически для любого приложения, которое использует значительное количество URL-адресов. Он делает SELECT URL по его полному тексту так же быстро, как он собирается получить. Второе преимущество заключается в том, что если вы сделаете этот столбец UNIQUE, вам не нужно беспокоиться о том, чтобы сделать столбец, хранящий фактический уникальный URL, и вы можете использовать REPLACE INTO и INSERT IGNORE как простые, быстрые операции атомной записи.

Я бы добавил, что использование встроенной функции MD5() MySQL просто отлично подходит для этой цели. Единственным недостатком является то, что выделенный атакующий может вызвать столкновения, и я уверен, что вас это не волнует. Использование встроенной функции делает, например, несколько типов соединений намного проще. Это может быть немного медленнее, чтобы передать полный URL-адрес по проводке ( "SELECT url FROM urls WHERE hash = MD5 (" verylongurl ")" вместо "WHERE hash = '32charhexstring" ), но у вас будет опция сделать это, если хотите. Если вы не придумаете конкретный сценарий, когда MD5() вас подведет, не стесняйтесь использовать его.

Трудный вопрос заключается в том, нужно ли и как вам искать URL-адреса способами, отличными от их полного текста: например, вы хотите найти все URL-адреса, начинающиеся с "/foo" на любом "bar.com" "хозяин? Пока" LIKE "% bar.com%/foo%" будет работать при тестировании, он потерпит неудачу в масштабе. Если ваши потребности включают в себя такие вещи, вы можете придумать творческие способы генерации индексов UNIQUE, ориентированных на тип данных, которые вам нужны... может быть, столбец domain_name, для начала. Вам нужно будет заполнить эти столбцы из своего приложения, почти наверняка (триггеры и хранимые процедуры намного сложнее, чем они стоят здесь, особенно если вас беспокоит производительность - не беспокойтесь).

Хорошей новостью является то, что реляционные базы данных очень гибки для такого рода вещей. Вы всегда можете добавить новые столбцы и заполнить их позже. Я бы предложил для начинающих: первичный ключ int unsigned auto_increment, уникальный хеш char (32) и (при условии, что хватает 64K символов). URL-адрес.

Ответ 2

Предположительно, вы говорите о целом URL-адресе, а не только о имени хоста, включая параметры CGI и другие материалы.

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

Существует два возможных подхода. Один - наивный и очевидный; он действительно хорошо работает в mySQL. Он имеет такие преимущества, как простота и возможность использовать URL LIKE "любой%" для эффективного поиска.

Но если у вас много URL-адресов, сконцентрированных в нескольких доменах... например...

http://stackoverflow.com/questions/3735390/best-primary-key-for-storing-urls
http://stackoverflow.com/questions/3735391/how-to-add-a-c-compiler-flag-to-extconf-rb

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

(Продукт серверного сервера Oracle имеет встроенный способ сделать это с помощью так называемого инвертированного индекса.)

Если бы я был вами, я бы избегал ключа автоинкремента, если вам не нужно присоединяться к более чем двум таблицам ON TABLE_A.URL = TABLE_B.URL или некоторым другим условиям соединения с этим видом мечения.

Ответ 3

Зависит от того, как вы используете таблицу. Если вы в основном выбираете с помощью WHERE url='<url>', то отлично, чтобы иметь таблицу с одним столбцом. Если вы можете использовать идентификатор автоинкремента, чтобы идентифицировать URL-адрес во всех местах вашего приложения, используйте автоинкремент