Запросы, планы, оптимизация запросов, ...
Модераторы: kdv, CyberMax
-
eg
- Сообщения: 17
- Зарегистрирован: 09 ноя 2005, 22:33
Сообщение
eg » 16 дек 2005, 00:01
Джойны это хорошо, увеличение скорости выполнения на порядок - это замечательно, но
avenger писал(а):И статистика при этом осталось точной. А я уже думал что пидется переходить к статистике с погрешностью.
Я в печали. Ну нету тут никакой погрешности, нету.
avenger писал(а):Для того что бы получить сколько человек учится всего мне осталось лишь просуммировать значения в поле COUNT(с помощью стороннего языка. Благо в php есть функция array_sum).
а это как раз будет _приблизительный_ ответ на вопрос "сколько человек учится всего?".
Позанудничаю: если "просуммировать значения в поле COUNT" твоего последнего запроса, то получится не "сколько человек учится всего", а сумма количеств "сколько человек учится на конкретно этом курсе" всего по всем курсам. А это не одно и то же: если один и тот же человек учится одновременно на нескольких курсах (а допускается ли такая ситуация по условию твоей задачи?) то он будет сосчитан
несколько раз. Отсюда и растут ноги "погрешности".
Хотя возможно, я туплю и брежу, так и не въехав в постановку задачи.
-
avenger
- Сообщения: 141
- Зарегистрирован: 25 окт 2005, 11:53
Сообщение
avenger » 16 дек 2005, 09:16
eg писал(а):Позанудничаю: если "просуммировать значения в поле COUNT" твоего последнего запроса, то получится не "сколько человек учится всего", а сумма количеств "сколько человек учится на конкретно этом курсе" всего по всем курсам. А это не одно и то же: если один и тот же человек учится одновременно на нескольких курсах (а допускается ли такая ситуация по условию твоей задачи?) то он будет сосчитан
несколько раз. Отсюда и растут ноги "погрешности".
Хотя возможно, я туплю и брежу, так и не въехав в постановку задачи.
Так мне как раз и надо, что бы человек был сосчитан каждый раз, если он учится на нескольких курсах. Погрешность бы была в том случае, если бы скажем он учится на 2-х курсах, а сосчитан 1 раз.
а допускается ли такая ситуация по условию твоей задачи?)
допускается.
Теперь всем можно спокойно вздохнуть, и выпить пива (за мой счет) виртуально.
Я про джоины читал и пользуюсь как правило неявными. Но при написании select-а, видел решении маленько с другой стороны. А вы мне помогли увидеть другое решение.
Всем море пЫва, и огромное спасибо!

-
eg
- Сообщения: 17
- Зарегистрирован: 09 ноя 2005, 22:33
Сообщение
eg » 16 дек 2005, 09:39
avenger писал(а):Так мне как раз и надо, что бы человек был сосчитан каждый раз, если он учится на нескольких курсах. Погрешность бы была в том случае, если бы скажем он учится на 2-х курсах, а сосчитан 1 раз.
Да-да-да!

Что ж ты так долго скрывал это?!

avenger писал(а):Теперь всем можно спокойно вздохнуть

avenger писал(а):Я про джоины читал и пользуюсь как правило неявными.
понимаешь, научиться синтаксису джойнов особых сложностей не составляет. Тут важно научиться правильно применять разные вариации для разных случаев и схем.
avenger писал(а):Но при написании select-а, видел решении маленько с другой стороны. А вы мне помогли увидеть другое решение.
Ну и напоследок, попробуй вот такой вот запрос, который вряд ли будет быстрее твоего последнего решения, но позволяет получить результат одной строкой, без перебора:
Код: Выделить всё
SELECT COUNT(DISTINCT(C.COURSEID*1000000+CLIENTFK))
FROM COURSES C, SUBJECTS S, CLIENTS2SUBJECTS CS
WHERE S.COURSEFK = C.COURSEID
AND S.SUBJECTID = CS.SUBJECTFK
AND C.COURSESTARTDATE <= 1136062799
AND C.COURSEENDDATE >= 1133384400
AND C.DIRDEPARTMENTFK=2
-
avenger
- Сообщения: 141
- Зарегистрирован: 25 окт 2005, 11:53
Сообщение
avenger » 16 дек 2005, 18:50
eg писал(а):Код: Выделить всё
SELECT COUNT(DISTINCT(C.COURSEID*1000000+CLIENTFK))
FROM COURSES C, SUBJECTS S, CLIENTS2SUBJECTS CS
WHERE S.COURSEFK = C.COURSEID
AND S.SUBJECTID = CS.SUBJECTFK
AND C.COURSESTARTDATE <= 1136062799
AND C.COURSEENDDATE >= 1133384400
AND C.DIRDEPARTMENTFK=2
Интересное решение.
Этот селект возврашает
Код: Выделить всё
План
PLAN (D INDEX (RDB$PRIMARY30))
PLAN JOIN (C INDEX (RDB$FOREIGN34),S INDEX (RDB$FOREIGN58),CS INDEX (RDB$FOREIGN48))
Адаптированный план
PLAN (D INDEX (INTEG_122)) PLAN JOIN (C INDEX (INTEG_126),S INDEX (INTEG_150),CS INDEX (INTEG_140))
------ Performance info ------
Prepare time = 0ms
Execute time = 16ms
Avg fetch time = 16,00 ms
Current memory = 2 292 620
Max memory = 2 474 112
Memory buffers = 90
Reads from disk to cache = 0
Writes from cache to disk = 0
Fetches from cache = 2 365
по сравнению с предидущим решением:
Код: Выделить всё
План
PLAN JOIN (C ORDER RDB$PRIMARY7,S INDEX (RDB$FOREIGN58),CS INDEX (RDB$FOREIGN48))
Адаптированный план
PLAN JOIN (C ORDER INTEG_27,S INDEX (INTEG_150),CS INDEX (INTEG_140))
------ Performance info ------
Prepare time = 0ms
Execute time = 16ms
Avg fetch time = 1,00 ms
Current memory = 2 291 704
Max memory = 2 474 112
Memory buffers = 90
Reads from disk to cache = 0
Writes from cache to disk = 0
Fetches from cache = 1 304
=> Время выполнения одинаковое.

-
Dimitry Sibiryakov
- Заслуженный разработчик
- Сообщения: 1436
- Зарегистрирован: 15 сен 2005, 09:05
Сообщение
Dimitry Sibiryakov » 19 дек 2005, 08:40
Я вот только не могу понять зачем нужен такой изврат: (C.COURSEID*1000000+CLIENTFK). То ли для нейтрализации DISTINCT то ли для обработки случаев когда один человек записался на один курс дважды.
По-моему, этот запрос должен давать тот же результат и с простым COUNT(*).
-
eg
- Сообщения: 17
- Зарегистрирован: 09 ноя 2005, 22:33
Сообщение
eg » 19 дек 2005, 09:52
Dimitry Sibiryakov писал(а):Я вот только не могу понять зачем нужен такой изврат: (C.COURSEID*1000000+CLIENTFK). То ли для нейтрализации DISTINCT то ли для обработки случаев когда один человек записался на один курс дважды.
Второй вариант. Трюк "имитирование позиционного кода".
Во времена, когда основным оружием пролетариата был клиппер, эта метода пользовалась огромной популярностью у знакомых мне программистов. Так, например, многосимвольный номенклатурный номер материала в себе содержал множественные признаки, группы, а-ля ссылки и т.д., отраженные в определенных позициях поля.
Вот и здесь идея заключается в формировании поля, первая часть которого представляет собой пк курса, а хвост - пк клиента-студента; формируем такие коды, исключаем дубликаты и подсчитываем результат.
Слабое звено этого подхода - завязка на максимальное количество CLIENTFK (млн.в данном случае).