Многоязычный дизайн БД с похожими переводимыми полями - PullRequest
0 голосов
/ 02 мая 2018

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

Итак, задача следующая:

  • Есть столик Items
  • Каждый Item имеет переводимый текст description_60, description_180, (номер суффикса обозначает тип сохраняемого описания, например, 60 означает длину 60 символов) и некоторые связанные поля каждому из них, например apiSourceName и т. д.

Я вижу два варианта:

1

descriptions_translations

  Id
description_60
description_180
description_300
apiSourceName_60
apiSourceName_180
....
...

, который выглядит не очень хорошо, так как мы можем получить множество пустых полей и

2

descriptions_60_translations
  Id
description_60
apiSourceName
languageId
...
...

3 Другое?

Я полностью открыт для других рекомендаций!

Также еще одна проблема заключается в том, что я хочу сохранить в основной таблице Item текст description_60. Возможно ли это без дублирования данных?

Обновление Склоняюсь к этому на основе ответов:

descriptions_translations
=========================
  id
itemId
description_type =>60, 120, 180 etc
`description` => 'This video is ...'
apiSourceName => youtube, dailymotion etc
languageId => en, es etc
...
...

Есть ли какие-либо недостатки в использовании одного и того же типа столбца для текстов длиной 60 и 1000 символов?

Ответы [ 3 ]

0 голосов
/ 02 мая 2018

Хороший способ сделать это и избежать отображения мусора для пользователей:

В поле «Предметы» укажите поле фактического описания. Например, в США (где мы отстаем по весам и показателям) это может быть:

Bread, brown, 1 pound loaf

Затем создайте таблицу перевода с тремя столбцами: lang, original, переведено`.

Например:

lang   original                     translated
 es    Bread, brown, 1 pound loaf   Hogaza de pan integral, 450g
 fr    Bread, brown, 1 pound loaf   Miche de pain brun, 450g
 de    Bread, brown, 1 pound loaf   Laib Schwarzbrot, 450g

Затем выполните запрос, подобный этому, чтобы получить перевод:

SELECT COALESCE(t.translated, i.name) as name
  FROM Items
  LEFT JOIN Translation t ON t.lang = 'se' AND i.name = t.translated

Таким образом, ваш шведский покупатель получит оригинальное название товара (пока вы не предоставите шведский перевод), а ваш мексиканский клиент получит соответствующий перевод. Хитрость заключается в шаблоне запроса COALESCE ... LEFT JOIN.

Возможно, вы захотите сопоставлять переводы по значениям идентификатора имени, а не по самим именам. Но, для чего стоит локализация в общих системах, таких как WordPress, совпадают по тексту имен, которые я предлагаю.

Редактировать Об эффективности использования текста для сопоставления, а не идентификаторов.

Допустим, у вас есть десять миллионов элементов в вашей таблице перевода. Это будет в среднем 200 байт на элемент. С индексами, скажем, 400 байт на элемент. Это 4 гигабайта для таблицы. Это будет стоить примерно от 0,11 до 0,14 долл. США в месяц в облачной машине высокого качества. Использование идентификатора будет чуть меньше половины этого. Скажем 1,5 гигабайта. Таким образом, разница составляет около 0,06 долларов США в месяц. Кроме того, облачные машины поставляются с минимальным объемом хранилища.

Поиск: если вы правильно проиндексировали свои таблицы, сопоставление текста не намного медленнее, чем сопоставление идентификаторов. И это произойдет не навалом, а когда люди будут искать информацию.

0 голосов
/ 19 мая 2018

Определите, какой максимальный размер столбца будет когда-либо , затем выберите из

  • Для «коротких» строк фиксированной длины (почтовый индекс, код страны, UUID и т. Д.) Используйте CHAR(..) CHARACTER SET ascii.

  • Для «коротких» строк, которые всегда будут «короткими», используйте VARCHAR(...) с пределом, который никогда не будет превышен. Выбранный лимит не имеет большого значения - 60 против 80 несущественны.

  • Для струн среднего размера рассмотрим VARCHAR(255). (Если вы используете 5.5 или 5.6 и utf8mb4, используйте 191.)

  • Для более длинных строк используйте TEXT (ограничение 64 КБ) или MEDIUMTEXT (ограничение 16 МБ).

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

Вряд ли кому-нибудь понадобится функция «отрубить мои строки по 60 символов». Если вам это нужно, то приложению, вероятно, нужно сделать больше, чем может сделать схема базы данных.

0 голосов
/ 02 мая 2018

Вам понадобится Languages table, как

Языки (идентификатор, имя)

Также вам понадобится ItemDescriptions table, например

ItemDescription (идентификатор, itemId, languageID, содержимое)

Вы будете insert values в Languages table, как

60, 'English' 
180, 'Hungarian'

записей в таблицу элементов, как

1, 'Toothpaste'

и записи в таблицу ItemDescription, например,

1, 1, 60, 'Best Toothpaste'
2, 1, 180, 'Legjobb Fogkrém'

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

EDIT

Оказывается, существует несколько языков и несколько описаний для каждого языка. Итак, нам нужно изменить определение ItemDescriptions на

ItemDescription (id, itemId, languageID, content60, content180, content300)

поэтому каждая запись будет содержать все соответствующие описания.

* * EDIT2 тысяча сорок-девять

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

Первое решение

ItemDescription (id, itemId, languageID, content, maxLength)

, где maxLength может быть 60, 180, 300 соответственно. Ваши дополнительные значения будут столбцами внутри ItemDescriptions table. Если вы используете varchar(300) для content, то вы не будете использовать ненужные байты для хранения значений в content.

Второе решение

ItemDescription80 (id, itemId, languageID, content)

ItemDescription180 (id, itemId, languageID, content)

ItemDescription300 (id, itemId, languageID, content)

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

* * Сравнение тысячи семьдесят-девять

Если вы используете varchar в качестве типа для content, то первый подход, по-видимому, превосходит второй с точки зрения простоты обработки, однако всякий раз, когда вы insert или update получаете значение там вам нужно убедиться, что maxLength является действительным (равно 60, 180 или 300 соответственно) и что content не длиннее maxLength. Вы можете сделать это из своего приложения или через уровень записи trigger on insert or update.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...