Форум "DataBase и SQL"
Язык запросов баз даных
Эффективность SQL-запросов (в частности в Firebird)Есть главная и подчиненные таблицы. Нужно создать выборку из главной и столбцом который отображает количество записей в подчиненной таблице. Я вижу два варианта. 1) select DD.ID, DD.NAME, DD.NAME_SHORT, DD.DISTRICT_TYPE_ID, count(RDSD.ID) as SALARY_DOC_COUNT from D_DISTRICT DD left join R_DISTRICT_SALARY_DOC RDSD on RDSD.DISTRICT_ID = DD.ID group by 1, 2, 3, 4 2) select DD.ID, DD.NAME, DD.NAME_SHORT, DD.DISTRICT_TYPE_ID, (select count(RDSD.ID) from R_DISTRICT_SALARY_DOC RDSD where RDSD.DISTRICT_ID = DD.ID) from D_DISTRICT DD Первый запрос получается неэффективен из-за большого количества полей в конструкции GROUP BY. Второй же получается для каждой записи главной таблицы КАЖДЫЙ раз фильтровать подчиненную. Может быть есть третий (более эффективный) способ?
|
|
#1 Mystic © 18.09.07 18:10:38
1. Некорректно сравнивать запросы, возвращающие разные данные 2. > Первый запрос получается неэффективен из-за большого количества полей в конструкции GROUP BY. Кто тебя так обманул? |
|
> #1 Mystic © почему разные? у меня одинаковые если тебя засмущал GROUP BY в первом запросе, то скажу что он реально не группирует записи в мастер таблице, потому что в группировку включен первичный ключ. GROUP BY там только для того, чтоб можно было посчитать COUNT для подчиненной таблицы. > Кто тебя так обманул? А разве операции группировки не считаются медленными? Особенно по полям типа varchar(200) ? гм... или встретив первое же различие (в моем случае - по первичному ключу) остальные сервером не выполняются? тогда запросы selectи selectдолжны значительно отличаться по скорости выполнения при условии, что в поле DD.NAME есть много значений которые отличаются например последней буквой. Так? |
|
если исходить из того что встретив первое же различие в значениях перечня полей, которые участвуют в выражении GROUP BY (в моем случае - это различие для мастер таблицы в первом же поле, по нему построен первичный ключ) остальные сервером не выполняются, то более эффективным можно считать первый скрипт. Правильно? |
|
#4 Mystic © 19.09.07 10:38:25
Отличие запросов в том, что если для некоторой записи в таблице D_DISTRICT нет записей в таблице R_DISTRICT_SALARY_DOC, то он возвращает единицу, а во втором случае нуль. Операция группировки эквивалентна сортировке результата запросы и вычислению агрегатных функций. Для интерпретатора SQL не составляет никакой проблемы в случае наличия в в списке группировки полей, принадлежащих уникальному индексу по таблице, исключить остальные поля из сравнения. Либо использовать дополнительно ROW_GUID (вначале сравниваем ROW_GUID, если он отличается, то сравниваем поля). Если тебя это очень парит, то сделай вьюшку: CREATE VIEW TblStat AS SELECT ID, COUNT(*) AS Cnt FROM TblStat GROUP BY IDи работай далее с ней: SELECT Tbl.*, Cnd FROM Tbl LEFT JOIN TblState ON Tbl.ID = TblStat.ID
|
|
> #4 Mystic © не совсем понял суть текста но пример меня вполне удовлетворил так, мне кажется, действительно будет эффективнее (а заодно и нагляднее). |
|
#6 Mystic © 19.09.07 13:10:50
Отмодерировал: Deep
|
|
#7 Mystic © 19.09.07 13:12:42
Смысл был в том, что серверу оптимизировать первый запрос раз плюнуть. |
|
> #7 Mystic © ну, собственно это как раз и интересно -- откуда у тебя такая увереность в способностях сервера по оптимизации? Оно вроде как понятно, сервер писали умные люди и все такое, но где об этом можно почитать или проверить? Только опытным путем? серверная оптимизация невидна "невооруженным" глазом, определенные выводы можно сделать исходя из плана запросов (но досконально его интерпретирвовать я пока не научился)... в остальном же, ИМХО, оптимизация сервера остается черным ящиком |
|
#9 Mystic © 19.09.07 14:34:09
В общем черный ящик, но я исхожу из того, что авторы не будут специально стремится сделать свой сервер тормознутым. Оптимизация же лежит на поверхности, поэтому, в моем представлении, она должна быть легко реализована. Например, в Delphi сравнение строк сделано так: вначале сравнивает указатели. Если они совпадают, то и строки совпадают. Если не совпадают, то надо сравнивать по содержимому. Это поведение достаточно логично. В любой DB есть понятие ROW_GUID. Это абсолюный адрес, по которому можно найти расположение строки в файле базы данных. Чтобы было легче. его можно представить как абсолютное смещение записи в фале базы данных. В Oracle эта информация доступна, в других базах данных она скрыта, но суть в том, что без этого написать хорошую базу данных нельзя. Так вот, нам надо сравнить две записи, которые относятся к одной таблице. По сути мы имеем в терминах сервера БД следующую команду: сравнить две строки из таблицы table1 по полям ID, Name, ... Так вот, будет ли разумно первым делом сравнить ROW_GUID? А потом уже сравнивать другие поля? Ибо если они совпадут, то сравнивать остальное это мартышкин труд. Далее, в случае, когда надо провести упорядочение строк по нескольким полям (ID, Name, ...), при этом порядок выбора не принципиален (группировка). Почему бы не вставить в это место ряд эвристик? Например, сравнение начинать с уникального ключа, а не с поля Name? Тоже я думаю, несложно реализуемо. Т. е. мы получаем, что с случае первого запроса сравнение по полям Name, NameShort выполняться не будет (с точки зрения здравого смысла) В вообще группировка по временным затратам эквивалентна сортировке. Временные затраты O(N*Log(N)). Само вычисление агрегатных функций есть величина порядка O(N).
|
|
о, теперь намного понятнее! респект за пояснения |
Написать ответ |
|
