DB, архитектурный вопрос.

bleyman

=)
Так вот, вопрос следующий: в базе данных есть некая древовидненькая структурочка. Вот такая, например: есть табличка с классами, табличка с учениками (для простоты - каждый ученик принадлежит классу табличка с оценками учеников. Требуется получить структуру в памяти, в которой есть все классы, в каждом классе - коллекция учеников, в каждом ученике - подмножество его оценок (выбирается при помощи ограничений по дате). Учеников около тысячи. Сейчас оно работает так: одним запросом выбираются все классы, на каждый класс идёт по запросу для выбора учеников, на каждого ученика идёт по запросу для выбора оценок. Итого больше тысячи запросов, каждый из которых бедная СУБД должна пропарсить, выполнить, вернуть данные, а потом программный интерфейс эти данные опять должен пропарсить. Тормозит.
Так вот, нормальные люди не испытывают неловкости, вытаскивая все оценки для всех учеников один раз (сразу сортируя по индексу ученика после чего эмулируя селект (учитывая сортированность) на этом массиве для каждого ученика?

alexkravchuk

Вообще, не проще ли сделать так, как это принято в SQL? Практика показывает, что работает это достаточно быстро.
table class(uid int(уникальный description varchar (250;
table students(uid int(уникальный class_id int(ид класса name varchar(250;
table ocenka(uid int(уникальный student_id int(ид ученика int ocenka, uid time);

также нужно построить индексы хотя бы для students.uid, students.class_id, ocenka.student_id, сlass.uid
Выборка производится запросом
select st.uid as student_uid, st.name as name, cl.description as class, oc.ocenka as ocenka
from class cl, students st, ocenka oc
where (st.class_id=cl.uid && st.uid=oc.student_id && time>time_0)
order by cl.uid, st.uid, time;

Может где немного наглючил, но смысл ясен, думаю.

bleyman

А не произойдёт ли недецкий пизд*ц, когда на каждого ученика будет выводится 20 копий ВСЕХ его данных, отличающихся только оценкой? Вот по-моему произойдёт, так что я иннер джоин с оцеками даже не рассматривал.

alexkravchuk

Это заведомо лучше, чем создавать кучу запросов.
Иногда оправдано, чтобы объединение происходило вне базы. Но и в этом случае не обязательно создавать такую кучу запросов, я бы в этом случае поступил одним из следующих способов (более того, такой способ имеет плюсы, так как описанный ранее не получит ученика, у которого вообще нет оценок).
Во-первых, получил одним запросом список классов и учеников, примерно так, как я предлагал в прошлый раз, но без оценок (хотя можно и воспользоваться тем, что будет описано ниже).
Далее получил бы оценки одним из вариантов:
Первый вариант, если нужно получить оценки для числа учеников, сравнимого со всеми (скажем, больше чем для 10%).
Тогда я просто сделал бы "select student_id,ocenka from ocenka_table where time>time0; ";, а далее, уже в программе, получал нужную тебе структуру.
Второй вариант, если нужно получить оценки для небольшого числа учеников, сильно меньшего, чем всего учеников в базе.
Тогда бы я сгенерировал в программе (а в некоторых случаях, если требуются ученики только из одного класса, например - просто оформил бы в виде вложенного или комбинированого select'а) строку вида in(uid1,uid2,uid3,...,uidN) где uid[i] - идентификатор соответствующего ученика, и сделал запрос вида
"select student_id,ocenka from ocenka_table where (time>time0 && student_id in(...; ";

Который будет работать заведомо лучше, чем отдельный запрос для каждого отдельного ученика, а накладные расходы при этом - минимальны.
Подобная ситуация у меня встречается регулярно, так как приходится работать с mysql версии 4.0.x и раньше (это та убогая версия, которая даже вложенных select'ов не понимает). Поступаю когда одним способом, когда - другим... Но делать огромное число запросов для чтения из БД - всегда неправильный подход.
PS: Я уже забыл про твой первый пост - ты примерно это и описывал. Вот ответ на твой вопрос: неловскость испытываю, особенно в случае с первым вариантом (второй лучше однако на практике регулярно так поступаю.

6yrop


Так вот, нормальные люди не испытывают неловкости, вытаскивая все оценки для всех учеников один раз (сразу сортируя по индексу ученика после чего эмулируя селект (учитывая сортированность) на этом массиве для каждого ученика?
Нормальные люди используют готовые решения -- DataSet-ы
Оставить комментарий
Имя или ник:
Комментарий: