Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Базы Данных > Эффективная организация базы


Автор: voidman 10.12.2008, 13:39
Здравствуйте!

С базами данных я немного знаком, но проффи себя назвать явно не могу. Возник вопрос по эффективной ("правильной", "распостраненной") организации оной.
Чтоб было понятно приведу простой пример.

Есть Фрукты:
1. Яблоко
2. Груша
..
n. Абрикос

Овощи:
1. Свекла
2. Морковь
...
n. Огурец

Есть дети, у которых могут быть и овощи и фрукты в произвольном порядке и количестве:
МАша - Яблоко, Абрикос  / СВекла
Денис - Яблоко                 / Морковь, Огурец

и т.д.

1. Как лучше всего организовать базу данных и записывать в нее значения фруктов/овощей если детей может быть от 500 до нескольких тысяч?
2. Задача в основном будет "НАйти всех детей у которых есть такой-то фрукт (или несколько фруктов) и/или такой-то овощь (несколько) "

________________________
Сейчас у меня так: 
Есть 3 таблицы: фрукты, овощи и основная.
В основной на против каждого ребенка (уникального айдишника) в своем столбце (Фрукты, Овощи, Напитки, Черт знает что еще)
идут айдишники из соответсвующих таблиц через запятую (1,2).

Весь этот вопрос возник потому, что если будет пара тысяч детей, несколько полей с огромной строкой вида "1,5,2,89,3,4,2,89,3,4,65..." поиск "Найти всех детей у которых есть такой-то фрукт (или несколько фруктов) и/или такой-то овощь (несколько) " может занять довльно много времени. То ли использовать Explode() для такой строки и потмо поиск значения, то ли strpos(), а может и сразу MYsql-овское LIKE?

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

Спасибо! 

Автор: bars80080 10.12.2008, 14:54
решается тем, что в таблице соответствий в одной записи есть всего один ребёнок с одним id (int) фрукта или овоща. 
это конечно увеличит количество записей в таблице, но вернёт базе функциональность

вообще фрукты и овощи можно было бы объединить в одну таблицу с разными id_category. 

Автор: Aliance 10.12.2008, 15:20
Прочитай в интернете про такое понятие: "Нормальная Форма". НФ существует окола 12, если не ошибаюсь, но каждая таблица должна быть приведена к 3-ей или 4-ой НФ (не помню точно).
Так вот, значений "через запятую" следует избегать.

Я бы сделал так:
Таблица 1 - продукты
ID продукта
Тип продукта (фрукт, овощ) - лучше сделать так же ID и вынести в отд. таблицу виды продуктов

Таблица 2 - Дети
ID ребенка
Его имя и прочая информация

Таблица 3 - Дети-Продукты
ID ребенка
ID продукта
количество

Автор: voidman 10.12.2008, 16:10
То есть, все сводиться к увеличению основной таблици в nn раз, где каждый ребенок повториться столько раз, сколько разных продуктов у него есть, так?
(это жутко огромная таблица может выйти, скажу я вам)

Осветите, плиз, основные негативные стороны работы с данными "через запятую".

Автор: SneG0K 10.12.2008, 16:16
Цитата(voidman @  10.12.2008,  15:10 Найти цитируемый пост)
работы с данными "через запятую"

Так у тебя будут хранится названия овощей (6-7 букв)
а так только ID (3-4 цифры)...

В общей сложности экономия будет несколько десятков килобайт...

Автор: voidman 10.12.2008, 16:27
Вроде основную фишку понял. Поправте, если что:

Создаю таблицы:
1. Фрукты
2. Овощи
3. Одежда

Потом таблицу
Дети (в которую входят какие-то уникальные поля для детей)

Дальше еще 3 таблицы:
1. Дети-фрукты
2. Дети-Овощи
3. Дети-Одежда

В каждой из этих таблиц будет Айдишник ребенка и Айдишник фрукта (овощм, одежды соответственно).

Потом, чтоб найти всех детей со специфическим условием - просто надо "прошерстить" все эти 3 таблицы взаимосвязей и отобрать "совпавших везде" детей.

Проверьте, пожалуйста, следующий запрос на "пригодность" (теоретически)

Код

SELECT name
FROM  Дети
WHERE Дети.id =   (SELECT id1 FROM  Дети-фрукты WHERE id2 = (SELECT id FROM фрукты WHERE name = "Мандарин"));



Этим запросом оно должно найти все имена детей, имеющих Мандарин. Правильно?






Автор: bars80080 10.12.2008, 18:06
а что, принципиально делить фрукты/овощи/одежда на три таблицы? нельзя в одной?

Автор: Валерия 10.12.2008, 18:13
Не = а IN

Автор: voidman 10.12.2008, 18:35
Цитата(bars80080 @ 10.12.2008,  18:06)
а что, принципиально делить фрукты/овощи/одежда на три таблицы? нельзя в одной?

А ведь, правда.. Сенкс )

Автор: Nigel 10.12.2008, 22:25
Вопрос о правильной структуре бд зависит прежде всего от задач, которые стоят перед вами.
Можно обойтись одной таблицей, если вы выполняете простейшие операции, к примеру: найти детей, у кого по 2 продукта, по 3... Если вам нужно определить сколько фруктов у пети, или сколько овощей у васи, то 2 таблицы. Если требуется найти сколько покупок(будь то фрукты, овощи) сделал тот или иной ребенок, то вот вам еще таблица. Идею, я думаю, поняли?
Aliance, да, в теории надо до 4-й формы доводить, вот только очень часто сталкиваюсь с денормализацией бд. Практика на то и практика, что в ней не всегда все как в теории...

Автор: bars80080 11.12.2008, 00:17
Цитата(Nigel @  10.12.2008,  21:25 Найти цитируемый пост)
Если вам нужно определить сколько фруктов у пети, или сколько овощей у васи, то 2 таблицы

в смысле две? на что две?

Автор: voidman 11.12.2008, 12:39
Цитата(Nigel @ 10.12.2008,  22:25)
Если вам нужно определить сколько фруктов у пети, или сколько овощей у васи, то 2 таблицы. Если требуется найти сколько покупок(будь то фрукты, овощи) сделал тот или иной ребенок, то вот вам еще таблица. Идею, я думаю, поняли?

Честно говоря, не совсем. Если возможно, приведите простейшие примеры для вышеописанного. До этого я не слыхал о Нормальных формах и работал в основном с одной таблицей, поэтому сейчас эта информация для меня в новинку и переключиться на "новое мышление" получается не сразу.



На данном этапе сделал 3 таблицы:
1. Дети (имя, возраст...)
2. "Товар", который у них может быть
(id  | category | product_name )
3. Дети-Товар
(id | child_id | category | product_id)  (категория тут нужна для разных функций, выборки и т.д. без "опроса других таблиц")


Пока, вроде, все работает как надо

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)