Нужен совет по простому дизайну MySQL db

Я пытаюсь создать простую базу данных элементов, используя MySQL для игры. Вот как мои 3 таблицы будут выглядеть как

     items
     itemId | itemName 
    -------------------
     0001   | chest piece
     0002   | sword
     0003   | helmet
     attributes (attribute lookup table)
     attributeId       | attributeName
     ---------------------------------
     01             | strength
     02             | agility
     03             | intellect
     04             | defense
     05             | damage
     06             | mana
     07             | stamina
     08             | description
     09             | type
     item_attributes (junction table)
     itemId  | attributeId   | value (mixed type, bad?)
     ------------------------------------
     0001   | 01            | 35
     0001   | 03            | 14
     0001   | 09            | armor
     0001   | 08            | crafted by awesome elves

     0002   | 09            | weapon
     0002   | 05            | 200
     0002   | 02            | 15
     0002   | 08            | your average sword

     0003   | 04            | 9000
     0003   | 09            | armor
     0003   | 06            | 250

Моя проблема с этим дизайном заключается в том, что столбец value в таблице item_attributes должен использовать тип данных varchar, так как данные значения могут быть int, char, varchar. Я думаю, что это плохой подход, потому что я не смог бы быстро сортировать свои объекты на основе определенных атрибутов. Это также пострадает от производительности, когда обрабатывается такой запрос, как получить элементы с силой атрибута, который имеет значение от 15 до 35.

Вот мое потенциальное исправление. Я просто добавил столбец data_type в таблицу attributes. Таким образом, это будет выглядеть примерно так.

     attributes (attribute lookup table)
     attributeId       | attributeName | data_type
     ---------------------------------------------------
     01             | strength      | int
     09             | type          | char
     08             | intellect     | varchar

Затем я бы добавил еще 3 столбца в таблицу item_attributes, int, char, varchar. Вот как выглядит новая таблица item_attributes.

     item_attributes (junction table)
     itemId  | attributeId   | value                 | int  | char | varchar
     ------------------------------------------------------------------------
     0002   | 09            | weapon                | null |weapon| null
     0002   | 05            | 200                   | 200  | null | null
     0002   | 02            | 15                    | 15   | null | null
     0002   | 08            | your average sword    | null | null | your average sword

Итак, теперь, если я должен сортировать элементы на основе его атрибута strength, я бы использовал столбец int. Или найдите элемент на основе его описания, я бы поискал столбец varchar.

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

Приветствуются любые входные данные.

Спасибо заранее.

РЕДАКТИРОВАТЬ 11/29/2010 Вот подробный список моих предметов.

--------------------------------------
http://wow.allakhazam.com/ihtml?27718
Aldor Defender Legplates
Binds when picked up
LegsPlate
802 Armor
+21 Strength
+14 Agility
+21 Stamina
Item Level 99
Equip: Improves hit rating by 14.
--------------------------------------
http://wow.allakhazam.com/ihtml?17967
Refined Scale of Onyxia
Leather
Item Level 60
--------------------------------------
http://wow.allakhazam.com/ihtml?27719
Aldor Leggings of Puissance
Binds when picked up
LegsLeather
202 Armor
+15 Agility
+21 Stamina
Item Level 99
Equip: Increases attack power by 28. 
Equip: Improves hit rating by 20.
--------------------------------------
http://wow.allakhazam.com/ihtml?5005
Emberspark Pendant
Binds when equipped
NeckMiscellaneous
+2 Stamina
+7 Spirit
Requires Level 30
Item Level 35
--------------------------------------
http://wow.allakhazam.com/ihtml?23234
Blue Bryanite of Agility
Gems
Requires Level 2
Item Level 10
+8 Agility
--------------------------------------
http://wow.allakhazam.com/ihtml?32972
Beer Goggles
Binds when picked up
Unique
HeadMiscellaneous
Item Level 10
Equip: Guaranteed by Belbi Quikswitch to make EVERYONE look attractive! 
--------------------------------------
http://wow.allakhazam.com/ihtml?41118
Gadgetzan Present
Binds when picked up
Unique
Item Level 5
"Please return to a Season Organizer"
--------------------------------------
http://wow.allakhazam.com/ihtml?6649
Searing Totem Scroll
Unique
Quest Item
Requires Level 10
Item Level 10
Use:  
--------------------------------------
http://wow.allakhazam.com/ihtml?6648
Stoneskin Totem Scroll
Unique
Quest Item
Requires Level 4
Item Level 4
Use:  
--------------------------------------
http://wow.allakhazam.com/ihtml?27864
Brian Bryanite of Extended Cost Copying
Gems
Item Level 10
gem test enchantment
--------------------------------------

EDIT # 2

  • Эти 10 примеров не являются репрезентативными для всех данных 35316 элементов, которые я собрал.
    • NeckMisc Miscellaneous означает, что элемент находится в обеих категориях `Neck` и` Misc`.
    • Уникальный означает, что для символа можно использовать только один элемент.
    • Не читайте слишком много в "Action", это просто описание квеста
    • Когда элемент говорит "Equip: увеличить силу атаки на 28", это означает, что сила атаки +28 на персонаже игрока. Это то же самое, что и маневренность +15.
  • В записи атрибутов элемента-атрибута содержится 241884 атрибута "один-ко-многим", так что примерно 241884/35316 ~ = 8 средних атрибутов на элемент. Также данные извлекаются из веб-сайта в гигантский текстовый файл. Для идентификации типа или категории элементов нет "хорошо сформированной" информации. Поэтому, если слово "меч" появляется на третьей или четвертой строках, оно автоматически классифицируется как меч.
  • Элемент может быть изменен при каждом новом обновлении игры.
  • Нет универсального атрибута, разделяемого между элементом, кроме `name`
  • Данные элемента доступны через веб-приложение. Неясно, что вы подразумеваете под битами и векторами?
  • Регулярное выражение используется на этапе разработки данных для очистки специального символа и поиска определенного ключевого слова, чтобы классифицировать элементы. Также для извлечения имени и значения атрибута. Например, +15 гибкость будет иметь гибкость строки, извлеченную как имя атрибута, и значение 15 в качестве значения. (Я не очень разбираюсь в вопросах 6 и 6.1. Slog означает серверный журнал здесь? Переводите регулярные выражения в SQL?)

Диаграмма моделей

Вот пример, как выглядит запрос

select *
from itemattributestat
where item_itemId=251

item_itemId | attribute_attributeId | value | listOrder
=======================================================
'251', '9', '0', '1'
'251', '558', '0', '2'
'251', '569', '0', '3'
'251', '4', '802', '4'
'251', '583', '21', '5'
'251', '1', '14', '6'
'251', '582', '21', '7'
'251', '556', '99', '8'
'251', '227', '14', '9'

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

create view itemDetail as
select Item_itemId as id, i.name as item, a.name as attribute, value
from ((itemattributestat join item as i on Item_itemId=i.itemId) 
    join attribute as a on Attribute_attributeId=a.attributeId)
order by Item_itemId asc, listOrder asc;

Вышеприведенный вид дает следующее с

select *
from itemdetail
where id=251;
id | item | attribute | value
'251', 'Aldor Defender' Legplates', 'Binds when picked up', '0'
'251', 'Aldor Defender' Legplates', 'Legs', '0'
'251', 'Aldor Defender' Legplates', 'Plate', '0'
'251', 'Aldor Defender' Legplates', 'Armor', '802'
'251', 'Aldor Defender' Legplates', 'Strength', '21'
'251', 'Aldor Defender' Legplates', 'Agility', '14'
'251', 'Aldor Defender' Legplates', 'Stamina', '21'
'251', 'Aldor Defender' Legplates', 'Item Level', '99'
'251', 'Aldor Defender' Legplates', 'Equip: Improves hit rating by @@.', '14'

Атрибут со значением 0 означает, что имя атрибута представляет тип элемента. 'Equip: Improves hit rating by @@.', '14' @@здесь владелец места, обработанный вывод в браузере будет 'Equip: Improves hit rating by 14.'

Ответ 1

Почему у вас есть таблица attribute ?

Атрибуты - это столбцы, а не таблицы.

Ссылка на сайт ничего не сообщает нам.

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

(надрез)

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

Исключением является PK, который полностью отображается и используется в той форме, где он является FK.

Просмотрите сайт и прочитайте некоторые вопросы SQL.

После этого вы можете подумать, хотите ли вы, чтобы strength и defense были атрибутами (столбцами) type; или нет. Et cetera.

Ответы на комментарии 30 ноября 10

.
Отлично, вы понимаете свои данные. Правильно. Теперь я понимаю, почему у вас есть таблица атрибутов.

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

    • Тип: Название жемчужина: Подвеска Emberspark... Или, является ли NeckMiscifferent типом?
    • Уникален ли ItemType? Я думаю, что не
    • Action.Display "Пожалуйста, вернитесь к организатору сезона"
    • Где находятся Attrinutes для AttackPower и HitRating?
      .
  • Сколько существует различных типов предметов (из 35 000), например, ala my Product Cluster. Другой способ заявить, что вопрос, сколько вариантов есть. Я имею в виду, значимо, а не 3500 элементов ÷ 8 Атрибутов?

  • Изменятся ли атрибуты item без изменения s/w (например, нового атрибута Inner Strength)?

  • Per Item, какие атрибуты повторяются (более одного); пока я вижу только действие?

  • Это игра, поэтому вам нужен db, который является жестким и очень быстрым, может быть, полностью резидентным. Нет нулей. Нет VAR. Кратчайшие типы данных. Никогда не дублируйте ничего (не повторяйте сами). Вы довольны битами (booleans) и векторами?

  • Вам нужно легко перевести эти регулярные выражения в SQL или вы довольны серьезным лозунгом для каждого (то есть, как только вы заработаете их на SQL, они довольно стабильны, а затем вы не входите в это с ним, если вы не найдете ошибку) (без сарказма, серьезного вопроса)?

    6.1 Или, может быть, это наоборот: db является резидентным диском; вы загружаете его в память один раз; вы запускаете регулярные выражения во время игры; время от времени запись на диск. Поэтому нет необходимости переводить регулярные выражения в SQL?

Здесь модель данных того, куда я направляюсь, это совсем не обязательно; он будет модулироваться вашими ответами. Чтобы быть ясным:

  • Шестая нормальная форма Строка состоит из Первичного ключа и, самое большее, одного Атрибута.

  • Я нарисовал (6.1) не (6), потому что ваши данные подтверждают мое убеждение, что вам нужна чистая реляционная база данных 6NF

  • Моя Модель данных кластера продуктов, пример лучше, чем EAV, равен 6NF, затем Нормализованный снова (не в смысле нормальной формы) с помощью DataType, чтобы уменьшить количество таблиц, которые вы уже видели. (Люди EAV обычно идут на один или несколько гигантских таблиц.)

  • Это прямой 5NF, только с двумя таблицами справа в 6NF.

Ссылка на модель игровых данных

Ссылка на IDEF1X Notation для тех, кто не знаком с стандартом реляционного моделирования.

Ответ на редактирование # 2 05 дек. 10

1,1. Хорошо, исправлено.

1,2. Затем IsUnique является индикатором (логическим) для элемента.

1,3. Действие. Я понимаю. Итак, где вы собираетесь его хранить?

1,4. NeckMiscellaneous означает, что элемент находится в обеих категориях Neck и Misc. Это означает два отдельных Item.Name=Emberspark Pendant, каждый из которых имеет другую категорию.

.
2. и 5. Таким образом, вам нужен быстрый быстрый резидентный db. Вот почему я пытаюсь передать вас через линию, вдали от GridLand, в RelationalLand.
.
3. Хорошо, мы остаемся с Пятой Нормальной Формой, не нуждаемся в 6NF или Кластере Продуктов (таблицы в Datatype). Sofar Values - это целые числа.
.
4. Я также вижу: Level, RequiredLevel, IsUnique, BindsPickedUp, BindsEquipped.
.
5. Биты - булевы {0 | 1}. Векторы необходимы для (реляционных) проекций. Мы доберемся до них позже. .
6. Хорошо, вы объяснили, что вы не переводите регулярные выражения в SQL. (Слог означает тяжелый труд). .
7. Что такое Category.ParentId? Родительская категория? Это еще не было. .
8. Атрибут .GeneratedId?

Пожалуйста, оцените модель данных (обновлено). У меня есть еще несколько столбцов, в дополнение к тому, что у вас есть. Если в модели данных вы ничего не понимаете, задайте конкретный вопрос. Вы прочитали документ "Нотация", верно?

У меня Action как таблица, с ItemAction с Value:
Equip: increase attack power by 28 составляет Action.Name= Increase attack power by и ItemAction.Value= 28.

Ответ 2

Я думаю, что столбец data_type еще больше усложняет дизайн. Почему бы просто не иметь столбцы type и description в таблице items? Разумеется, каждый элемент будет иметь каждое из этих значений, а если это не так, то null будет отлично работать в текстовом столбце.

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

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

Ответ 3

Вы имеете дело с двумя распространенными проблемами:

  • Сущности, похожие друг на друга, но не идентичные (все элементы имеют имя и описание, но не обязательно интеллект).
  • Конструкция, в которой вам нужно добавлять атрибуты, когда база данных находится в процессе производства (вы можете легко предсказать, что в какой-то момент вам нужно будет добавить, например, атрибут магии для некоторых элементов).

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

В этом случае я бы лично пошел с решением на полпути между реляционным и EAV. Я бы взял общие столбцы и добавил их в виде столбцов в таблицу элементов или, если элементы представляют виды элементов, а не отдельные, в таблицу items_owners. Эти столбцы будут включать описание и, возможно, тип и в примере, который вы дали, в значительной степени совпадают с текстовыми столбцами. Затем я сохранил существующий макет для тех атрибутов, которые являются числовыми рейтингами, делая тип значения int. Это дает вам проверку типов и правильную нормализацию по целочисленным атрибутам (вы не будете хранить много NULL) за счет случайного типа или описания NULL.