Нужна подсказка по простому дизайну БД MySQL - PullRequest
2 голосов
/ 27 ноября 2010

Я пытаюсь создать простую базу данных предметов, используя 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 соответствует тому, что я ищу.

Будем благодарны за любые материалы.

Заранее спасибо.

РЕДАКТИРОВАТЬ 29.11.2010 Вот подробный список моих вещей

--------------------------------------
http://wow.allakhazam.com/ihtml?27718
Aldor Defender's 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's Bryanite of Extended Cost Copying
Gems
Item Level 10
gem test enchantment
--------------------------------------

РЕДАКТИРОВАТЬ # 2

  1. Эти 10 примеров не являются репрезентативными для всех 35316 данных, которые я собрал.
  2. NeckMiscellaneous означает, что предмет относится к обеим категориям: «Neck» и «Misc».
  3. Уникальный означает, что только один элемент может быть использован для персонажа.
  4. Не читайте слишком много в "Действие", это просто описание квеста
  5. Когда предмет говорит: «Надеть: увеличить силу атаки на 28», это просто означает +28 к силе атаки персонажа игрока. Это +15 к ловкости.
  6. Всего имеется 241884 записей атрибутов элемента «один ко многим», что составляет 241884/35316 ~ = 8 средних атрибутов на элемент. Также данные добываются с веб-сайта в гигантский текстовый файл. НЕТ «правильно сформированной» информации для определения типа или категории предмета. Таким образом, если слово «меч» появляется в 3-й или 4-й строке, оно автоматически классифицируется как меч.
  7. Предмет может меняться при каждом новом обновлении игры.
  8. Нет универсального атрибута, доступного для элемента, кроме `name`
  9. Данные об элементе доступны через веб-приложение. Неясно, что вы подразумеваете под битами и векторами?
  10. Регулярное выражение используется на этапе интеллектуального анализа данных для очистки специального символа и поиска определенного ключевого слова для классификации элементов. Также для извлечения имени и значения атрибута. Например, +15 к ловкости будет иметь строковую ловкость, извлеченную как имя атрибута, и 15 как значение. (Я не очень разбираюсь в вопросах 6 и 6.1. Слог здесь обозначает журнал сервера? Перевести регулярные выражения в 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''s Legplates', 'Binds when picked up', '0'
'251', 'Aldor Defender''s Legplates', 'Legs', '0'
'251', 'Aldor Defender''s Legplates', 'Plate', '0'
'251', 'Aldor Defender''s Legplates', 'Armor', '802'
'251', 'Aldor Defender''s Legplates', 'Strength', '21'
'251', 'Aldor Defender''s Legplates', 'Agility', '14'
'251', 'Aldor Defender''s Legplates', 'Stamina', '21'
'251', 'Aldor Defender''s Legplates', 'Item Level', '99'
'251', 'Aldor Defender''s Legplates', 'Equip: Improves hit rating by @@.', '14'

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

Ответы [ 3 ]

3 голосов
/ 28 ноября 2010

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

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

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

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

(надрез)

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

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

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

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

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

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

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

    • Тип: Драгоценный камень Имя: Подвеска Emberspark ... Или это шейка Разное?
    • Является ли Unique истинным ItemType? Я думаю, что нет
    • Action.Display "Пожалуйста, вернитесь к организатору сезона"
    • Где находятся атрибуты для AttackPower и HitRating?
      .
  2. Сколько существует различных типов товаров (из 35 000), как пример моего кластера продуктов. Другой способ сформулировать этот вопрос - сколько существует вариантов. Я имею в виду, по сути, а не 3500 предметов ÷ 8 атрибутов?

  3. Изменится ли item_attributes без выпуска программного обеспечения (например, новый атрибут Inner Strength)?

  4. За элемент, какие атрибуты повторяются (более одного); пока вижу только экшн?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2 голосов
/ 27 ноября 2010

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

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

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

0 голосов
/ 28 ноября 2010

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

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

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

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

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