Всем php-субботникам привет. Интересно мнение всех, особенно тех кто использовал хранение языковых свойств в json. Стою перед выбором, как реализовывать языковую часть. Будет информационный портал - соответственно текста много. Поиск по тексту меня не парит, но будет еще категория позиций с фильтрами. CRUD+ui генератор админки для laravel по умолчанию генерит для себя одну таблицу в которой хранит json типа name {ru:{value:НоваяНовость}, en:{value:NewNews}}, соответственно description{ru:{value: длиннющий текст}, en:{value: loonger text}} Я вот думаю, пойти на поводу админки или же по старинке вынести языковую часть в отдельную таблицу. Что будет дальше по мере нарастания нагрузки на проект и возможного увеличения количества языков?
lang | name| description --------- en | ...| loonger text ru | ...| длиннющий текст fr | ...| texte long --- Добавлено ---
да, я тоже склоняюсь к этому. т.к. таскать за собой тонну не запрошенных данных - выльется в бабло на мощный сервер. кстати, если есть опыт по глобальным мультиязычным проектам (у меня были пока только ru/en не требующие изменений в slug), slug оставлять для всех единым или так же для разных языков свой?
Не хочешь таскать незапрошенные данные - не запрашивай их. Оба метода рабочие и действительные. У обоих методов есть и косяки, и плюсы. Есть и третий вариант - перевод каждого языка хранить в своей отдельной таблице. И у всех методов есть причина, почему именно так. Собственно говоря, перейти от одного метода к другому в случае необходимости - дело вечера. Мой совет: не заморачиваться, оставить всё из коробки. А вот когда придёт время и что-то будет уже видно тормозить - тогда и думать. Только тогда уже можно будет найти узкое место и принимать решение исходя из этого, а не наобум.
и если не сложно, опять же, было бы интересно понять - насколько тяжело для б.д. если хранить все текстовые поля, в которых будут содержаться языковые объекты, в формате json, а не string
Ну начнём. Говорить будем о переводе информации, а не о переводе интерфейса. Перевод интерфейса тоже можно хранить в базе, но с ним всё проще. Нам не надо по нему делать поиск, как минимум. Хотя интерфейс лично я обычно храню в файлах локализации, а не в бд. Но тут уже кому как удобней, на самом деле. Так вот, в чём сложность перевода именно информации - нам придётся делать по ней поиск. А учитывая, что это большие тексты порой, то нужен полнотекстовый поиск. Мы же не будем like'ть, правда? Первый вариант - это вариант, предложенный мышезверем: Код (Text): lang | name| description --------- en | ...| loonger text ru | ...| длиннющий текст fr | ...| texte long Плюсы: нет гемора с json, одна таблица для всех языков (удобненько ведь), есть возможность полнотекстового поиска. Но тут же натыкаемся на минусы: таблица слишком разрастается. Т.е. до определённого момента всё норм, можно не напрягаться. Но как только на сайте будет достаточно информации - могут начаться тормоза. Например, у нас есть 5 языков, и 2 миллиона текстов. 2 миллиона строк в бд - вполне нормальная цифра. Но т.к. у нас в таблице все языки лежат в куче, то строк у нас на ровном месте получается уже не 2 миллиона, а 10. Ну и в данном случае придётся использовать составной индекс из двух столбцов - en+name. Вывод: если нет очень больших данных, то вполне норм вариант. Второй способ - тоже самое, только для каждого языка отдельная таблица. Это ровно такой же способ, как и предыдущий, за исключением нам не надо создавать составной индекс, ограничимся одним name. Язык=таблица, собственно язык мы уже определили где искать. Собственно, это самый обыкновенный горизонтальный шардинг данных. Плюсы: нет гемора с json, таблица не разрастается, есть возможность полнотекстового поиска. Минусы: для каждого нового языка придётся лезть и править бд. А если данных даже тут будет очень много, то придётся все эти таблицы тоже шардить. И шардинг тут получится посложнее, чем в первом варианте. Вывод: тоже вполне себе вариант, даст возможность работать с более объёмными данными, чем первый. Но опять же "до поры до времени". И третий вариант - использование JSON. Тут есть два варианта использования. 3.1 Текстовое поле, в который просто строкой пульнуть json. Плохой вариант для полнотекстового поиска. Т.е. нельзя нормально взять и сделать поиск по такому полю, ибо получится много лишнего шума. Для целей полнотекстового поиска я этот вариант не буду даже рассматривать. 3.2 Использование специального типа JSON. Вот тут интересностей уже больше. Плюсы: одни таблица, в случае больших данных простой шардинг. Минусы: без дополнительных действий нет возможности полнотекстового поиска. MySQL (да и вроде PostreSQL, хотя тут я не совсем уверен) не умеет делать полнотекстовый поиск по json-полям напрямую. Для этого придётся делать генерированные поля. Т.е. есть возможность сделать дополнительные поля из JSON. Например, есть json PHP: { "name" : "ololo", "description" : "описанька" } Можно сказать базе данных, чтобы она создала столбец, например, с нвазванием: PHP: `names_generic` VARCHAR(255) GENERATED ALWAYS AS (`JSON` ->> '$.name') Собственно указать, что поле names_generic генерируется из ключа name в json. Теперь на этот столбец можно будет навесить индекс и сделать полнотекстовый поиск. Способ следует выбирать не "а вдруг у меня через 10 лет будет 20 миллионов записей", а из реальных фактов. Усложнять систему ради "мифической возможной нагрузки" не надо. Если придёт время - можно будет отрефакторить и сменить способ опять же из появившихся нужд. Нет идеального варианта. Есть задача и есть лучший способ решить эту конкретную задачу.
да, обычно с таким заделом начинаем делать, а через три года проекта нет вообще)) пожалуй действительно стоит попробовать из коробки json решение. по крайней мере сэкономит время, да и опыт работы пригодится. все же какой-то wordpress живет с этим и довольно популярно живет. хотя, конечно, иногда приходится лезть руками в базу и вычищать, т.к. любит генерировать и тягать за собой тонны данных, особенно woocommerce спасибо за мнение и развернутый ответ!