За последние 24 часа нас посетили 21586 программистов и 1031 робот. Сейчас ищут 726 программистов ...

Язык хранить в отдельной таблице или в json

Тема в разделе "PHP и базы данных", создана пользователем rewuxiin, 19 окт 2019.

  1. rewuxiin

    rewuxiin Активный пользователь

    С нами с:
    17 апр 2012
    Сообщения:
    611
    Симпатии:
    87
    Всем php-субботникам привет.

    Интересно мнение всех, особенно тех кто использовал хранение языковых свойств в json.

    Стою перед выбором, как реализовывать языковую часть.
    Будет информационный портал - соответственно текста много. Поиск по тексту меня не парит, но будет еще категория позиций с фильтрами.

    CRUD+ui генератор админки для laravel по умолчанию генерит для себя одну таблицу в которой хранит json типа name {ru:{value:НоваяНовость}, en:{value:NewNews}}, соответственно description{ru:{value: длиннющий текст}, en:{value: loonger text}}

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

    Что будет дальше по мере нарастания нагрузки на проект и возможного увеличения количества языков?
     
  2. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.752
    Симпатии:
    1.322
    Адрес:
    Лень
    lang | name| description
    ---------
    en | ...| loonger text
    ru | ...| длиннющий текст
    fr | ...| texte long
    --- Добавлено ---
     
  3. rewuxiin

    rewuxiin Активный пользователь

    С нами с:
    17 апр 2012
    Сообщения:
    611
    Симпатии:
    87
    да, я тоже склоняюсь к этому. т.к. таскать за собой тонну не запрошенных данных - выльется в бабло на мощный сервер.

    кстати, если есть опыт по глобальным мультиязычным проектам (у меня были пока только ru/en не требующие изменений в slug), slug оставлять для всех единым или так же для разных языков свой?
     
  4. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    Не хочешь таскать незапрошенные данные - не запрашивай их.
    Оба метода рабочие и действительные. У обоих методов есть и косяки, и плюсы.
    Есть и третий вариант - перевод каждого языка хранить в своей отдельной таблице.
    И у всех методов есть причина, почему именно так.

    Собственно говоря, перейти от одного метода к другому в случае необходимости - дело вечера. Мой совет: не заморачиваться, оставить всё из коробки. А вот когда придёт время и что-то будет уже видно тормозить - тогда и думать. Только тогда уже можно будет найти узкое место и принимать решение исходя из этого, а не наобум.
     
  5. rewuxiin

    rewuxiin Активный пользователь

    С нами с:
    17 апр 2012
    Сообщения:
    611
    Симпатии:
    87
    если не сложно, можно кратко о косяках и плюсах?
     
  6. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    Завтра ближе к вечеру, сегодня совсем нет времени
     
    rewuxiin нравится это.
  7. rewuxiin

    rewuxiin Активный пользователь

    С нами с:
    17 апр 2012
    Сообщения:
    611
    Симпатии:
    87
    и если не сложно, опять же, было бы интересно понять - насколько тяжело для б.д. если хранить все текстовые поля, в которых будут содержаться языковые объекты, в формате json, а не string
     
  8. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    Ну начнём.
    Говорить будем о переводе информации, а не о переводе интерфейса. Перевод интерфейса тоже можно хранить в базе, но с ним всё проще. Нам не надо по нему делать поиск, как минимум. Хотя интерфейс лично я обычно храню в файлах локализации, а не в бд. Но тут уже кому как удобней, на самом деле.
    Так вот, в чём сложность перевода именно информации - нам придётся делать по ней поиск. А учитывая, что это большие тексты порой, то нужен полнотекстовый поиск. Мы же не будем like'ть, правда?

    Первый вариант - это вариант, предложенный мышезверем:
    Код (Text):
    1. lang | name| description
    2. ---------
    3. en | ...| loonger text
    4. ru | ...| длиннющий текст
    5. 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:
    1. {
    2.     "name" : "ololo",
    3.     "description" : "описанька"
    4. }
    Можно сказать базе данных, чтобы она создала столбец, например, с нвазванием:
    PHP:
    1. `names_generic` VARCHAR(255) GENERATED ALWAYS AS (`JSON` ->> '$.name')
    Собственно указать, что поле names_generic генерируется из ключа name в json. Теперь на этот столбец можно будет навесить индекс и сделать полнотекстовый поиск.

    Способ следует выбирать не "а вдруг у меня через 10 лет будет 20 миллионов записей", а из реальных фактов. Усложнять систему ради "мифической возможной нагрузки" не надо. Если придёт время - можно будет отрефакторить и сменить способ опять же из появившихся нужд. Нет идеального варианта. Есть задача и есть лучший способ решить эту конкретную задачу.
     
    rewuxiin нравится это.
  9. rewuxiin

    rewuxiin Активный пользователь

    С нами с:
    17 апр 2012
    Сообщения:
    611
    Симпатии:
    87
    да, обычно с таким заделом начинаем делать, а через три года проекта нет вообще))

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

    все же какой-то wordpress живет с этим и довольно популярно живет. хотя, конечно, иногда приходится лезть руками в базу и вычищать, т.к. любит генерировать и тягать за собой тонны данных, особенно woocommerce

    спасибо за мнение и развернутый ответ!