Как грамотно сделать поиск по фильтрам и где хранить характеристики?
Здравствуйте, подскажите пожалуйста как правильно хранить характеристики товаров для последующей выборке через фильтры? Сейчас у меня все фильтры привязаны по id к каждой категории, у каждого фильтра соответственно свое имя поля, так вот, существует также таблица в которой хранится около 50 тыс товаров, ну и соответственно все имена фильтров , которые существуют аналогично созданы и в таблице товаров, образно говоря 200 штук фильтров по характеристикам и 200 полей в таблице товаров с этими же именами, естественно у каждого товара 20-30 полей заполнено, а остальные со значением null, логично, что это полнейший бред, да и работает это с каждым новым полем медленнее и медленнее, если добавить еще 200 полей с фильтрами, а мне нужно их больше 1500 тыс, то сервер mysql вообще ляжет после 100 одновременных запросов, как сделать так, чтобы были заполнены для каждого товара только нужные поля без всяких null, и не в одной таблице с товарами , плюс так чтобы можно было по этим полям делать поиск, т.е без json. Не совсем понимаю, как быть если фильтров 1500 тысячи и соответственно вариантов полей, так или иначе получается, что все равно нужно чтобы было 1500 полей в какой-то таблице, но в mysql столько полей и не создать на сколько я знаю в одной таблице
Не вижу, отчего это всё должно работать "медленнее и медленнее". Откуда такие фантазии?
Все держать в одной таблице - это хотя и неудобное, но самое простое и быстрое решение. Остальные будут заведомо медленнее (если говорить про поиск средствами самой mysql). А если искать внешним движком, то и JSON не проблема.
Ипатьев, т.е если я создам в одной таблице 1500 полей, если это вообще возможно, то никаких дополнительных нагрузок и особых проблем не возникнет? Мне казалось, что поиск сразу по 10 -15 полям в таблице с 200 полями медленнее, чем скажем в таблице в которой 50-70 полей. Сколько вообще в MySQL максимум полей может быть на одну таблицу, где-то написано 4096, где-то 266? Если потребуется больше, чем доступно, добавлять ещё одну таблицу и просто искать уже по полям из 2 таблиц? Например в одной будет тогда 4096 полей и в другой ещё столько же, хотя поиск по факту будет исключительно по максимум 10-20, нормально все пройдёт? Просто не хочется зря время потратить, и потом переделывать
У меня вопрос был не про таблицы, а про замедление.
Я не вижу, с какой радости "с каждым новым полем будет медленнее и медленнее".
Если это факт, то с ним и надо разбираться. Что именно медленнее, насколько медленнее.
Если это фантазии, то не надо на них строить всю архитектуру приложения.
Если вам нужно миллион полей и чтобы это быстро работало, то берите PostgreSQL и делайте поле JSONB, и храните там любой размерности таблицы в формате JSON.
MySQL умеет только в обычный JSON, а он гораздо медленнее чем тип JSONB.
Единственно когда может просеть производительность, если вы массово будет обновлять JSONB в которых хранится данные по несколько мегабайт, но при чтение всё будет летать.
П.С Но тогда можно вообще использовать специальный СУБД, например MongoDB или ему подобные решения :)
tukreb, MongoDB использовать не надо.
Если в вашей БД отсутствует структура, то надо менять не базу данных, а DBA
Учитывая же, что внешний поисковый движок все равно будет нужен, как для фасетного, так и для живого поиска по товарам, то разница между JSON полями - не та причина, по которой меняют MySQL на PostgreSQL. Что бы себе любители решать чужие проблемы в интернете не думали.
Для неоднородных сущностей с произвольными наборами свойств обычно используют EAV таблицы, что позволяет создать любой набор свойств для любого экземпляра сущности (например уникальные свойства для каждого товара).
Минус - для поиска нужно строить достаточно объемные запросы, не помещающиеся в обычную логику по типу "селект вэа..." и требующие некоторого конструктора запросов. Так же, в большинстве случаев скорость запросов будет падать с ростом используемых атрибутов, но тут как раз нужно будет использовать фасетный поиск, то есть для группы товаров можно резко ограничить выборку через признак группы атрибутов, свойственные только этой группе, что сужает выборку и ускоряет поиск по тарибутам.
ThunderCat, спасибо, сейчас как раз вернулся к этому моменту. Я все равно не совсем понимаю как именно мне производить поиск по товарам и как выстроить цепочку запросов для поиска, просто по тому как я это понял, у меня получится огромный список Id товаров, который разве что получится в конечном счете вставить в IN, но это тоже не вариант, товаров будет например 500 , это не выход. Сейчас у меня бд(MySQL) выглядит так, таблица со списком фильтров связанная с категориями и таблица с товарами, когда человек выбирает фильтры, то названия полей в таблице с фильтрами имеют такое же название в таблице с товарами, ну и соответственно так и ищу. Но я не понимаю как должна выглядеть промежуточная таблица в которой будут храниться свойства товаров? К одному товару 50 записей что ли добавлять на каждую позицию? Например таблица будет иметь 3 столбца(product_id, name_filter, attribute), допустим я буду искать в этой таблице по названию фильтра и атрибуту, допустим что-то найду, например 500 записей, получу их product_id, а дальше что с этим делать? Вставить 500 штук Id в in и вытащить эти товары из таблицы где хранятся все товары? В конечном счете получается все равно очень тяжелый запрос, на этом моменте торможу, или вообще должна быть другая логика?
___
Сейчас подумал ещё, как вариант left join’ом тянуть совпадающие Id, на сколько это сложные будут запросы?
у меня получится огромный список Id товаров, который разве что получится в конечном счете вставить в IN, но это тоже не вариант, товаров будет например 500 , это не выход.
500 это просто копейки, вполне можно использовать in, другой вопрос что проще и правильней иметь таблицу соединений категория-атрибут_ид, и искать только в соединении атрибутов вэа ин (все атрибут_ид категории), которых обычно штук 20 на категорию. Интереснее будет с конструктором запроса для поиска, так как есть поля с логикой and, так и с логикой or... Я бы на вашем месте для начала сделал конструктор, а потом добавлял ограничения на соединения и делал соответствующие таблицы.