@NewTypes
На себя

Красивые URL и поиск по БД — как вы с этим работаете?

Я имею ввиду классическую задачу - найти slug страницы, поле в таблице БД ответственное за красивые URL. Допустим мне нужна страница site.com/pretty-url и я начинаю искать в поле slug значение "pretty-url". Но ведь это же затратно (или БД сама за меня решит эту проблему быстрого поиска? Учитывая, что для каждой записи изначально проставлены ID).

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

  • Вопрос задан
  • 3641 просмотр
Пригласить эксперта
Ответы на вопрос 10
schmooser
@schmooser

Если есть индекс на этом поле, то скорость поиска будет примерно такая же как и при доступе по id. Там точно такой же индекс, только не по тексту а по числу.

Ответ написан
@timathecue

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

Ответ написан
DrNemo
@DrNemo

Основной минус хранения красивого урла в БД - это дополнительный запрос. если страниц которым требуется такой урл не много, то по-моему проще его хранить в простом массиве, в отдельном файле

return array('my_castom_url_page' => 'real_url_page', ...);

Ответ написан
@kaasius

Если посещаемость сайта не несколько миллионов человек в сутки, беспокойство лишнее. Знаю это не по теории, а из практики, у меня так работают сайты примерно c 2000 года, проблем c быстродействием поиска не наблюдается. Если же посетителей становится много, наверняка захочется сделать кеширование в redis например. Лучше подумать, что произойдет, когда захочется сделать иерархию (/uri, /uri/suburi и т.д.). Тут тоже проблемы особо нет, но задача точно поинтереснее.

Ответ написан
Комментировать
FanatPHP
@FanatPHP
Чебуратор тега РНР

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

Для компьютера и число и строка - это набор байт. Что конкретно в эти байты записано - ему всё равно. Поиск по упорядоченному набору байт будет производиться одинаково.

Не стоит заранее переживать за производительность. От этого одни проблемы.

Ответ написан
Комментировать
AGvin
@AGvin

В данном случае, зачем сразу к БД лезть? Ведь есть такая вещь как кеши. В качестве ключа использовать "префикс" + CRC32(URL).

Ответ написан
Комментировать
grendel
@grendel

Как вариант, можно работать с урлом такого вида site.com/id/pretty-url, и попросту игнорировать часть "pretty-url". Посмотрите по новостным сайтам - некоторые именно так работают.

Upd. Не заметил ваш комментарий выше. Тогда да, индексирование по полю урла будет работать сносно.

Ответ написан
Комментировать
afiskon
@afiskon

SELECT ... FROM articles WHERE slug = .... (LIMIT 1) ну и индекс по полю slug конечно же!

Ответ написан
Комментировать
alekciy
@alekciy
Вёбных дел мастер

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

Ответ написан
Комментировать
@romeo7
Для быстрого поиска по БД, если выборка осуществляется по текстовому полю, в вашем случае по "красивому" урл-у, предлагаю два варианта:
Вариант 1. Индексация поля, как FULLTEXT с фиксированной длиной, к примеру 255 символов.
Минусы: Избыточный индекс + проблема СУБД MySQL в использования FULLTEXT индекса на движке InnoDB (доступно MySQL >= 5.6).

Вариант 2. Добавить добавить дополнительное поле с бинарный хэшом этого урл-а.
Как сделать:
Предположим, что в таблице articles, существует поле url, создаём дополнительное поле url_hash с типом "binary" длиной 16.
Запрос на добавление бинарного хэша
UPDATE articles SET url_hash=UNHEX(MD5(url));
Запрос на выборку по бинарному хэшу
SELECT * 
FROM articles
WHERE url_hash =  UNHEX(MD5('pretty-url'));

Если данных много, то во избежании коллизий можно добавить префикс к хэшу, к примеру, название таблицы:
UNHEX(MD5(CONCAT('pretty-url', 'articles')))
Плюсы: Быстрый индекс с фиксированной длиной.
Минусы: Избыточные данные в виде дополнительного поля.
Данный вариант, считается Best практикой:
MySQL binary against non-binary for hash IDs
Тест производительности
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы