|
Оптимальны ли запросы ? | ☑ | ||
---|---|---|---|---|
0
zak555
04.09.11
✎
13:47
|
ковыряю тут запросы в 8
пусть есть два справочника Сотрудники (иерархический справочник) и подчинённый ему Дети написать запросы : 1. получить всех сотрудников, имеющих детей 2. -||- без детей 1. "ВЫБРАТЬ РАЗЛИЧНЫЕ | Дети.Владелец.Ссылка |ИЗ | Справочник.Дети КАК Дети" 2. "ВЫБРАТЬ | Сотрудник.Представление |ИЗ | Справочник.Сотрудники КАК Сотрудник |ГДЕ | (НЕ Сотрудник.Ссылка В | (ВЫБРАТЬ РАЗЛИЧНЫЕ | Дети.Владелец.Ссылка | ИЗ | Справочник.Дети КАК Дети)) | И Сотрудник.ЭтоГруппа = ЛОЖЬ" |
|||
6
kosts
04.09.11
✎
13:58
|
второй запрос
ВЫБРАТЬ Сотрудник.Представление ИЗ Справочник.Сотрудники КАК Сотрудник левое соединение Справочник.Дети КАК Дети по Сотрудник.ссылка = Дети.Владелец.Ссылка где Дети.Ссылка есть null |
|||
7
kosts
04.09.11
✎
14:01
|
(5) что так что так запрос обойдет 1000000 элементов.
Только вернет разное количество. |
|||
8
Armando
04.09.11
✎
14:01
|
Что тебя смущает в этих запросах?
|
|||
9
kosts
04.09.11
✎
14:02
|
В запросах 1С не рекомендуется использовать конструкцию "В", потому что не всегда делаются оптимальные планы.
|
|||
10
Armando
04.09.11
✎
14:04
|
(9) при этом сами ее активно используют в шаблонах рлс
|
|||
11
kosts
04.09.11
✎
14:07
|
(10) Историю кто то выкладывал. Что то вроде "Типовые конфигурации 1С не имеют статуса совместимо с 1С"...
|
|||
12
zak555
04.09.11
✎
14:11
|
(6) ха, про "ЕСТЬ NULL" не знал, как пользоваться
"ВЫБРАТЬ | Сотрудник.Представление |ИЗ | Справочник.Сотрудники КАК Сотрудник | ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Дети КАК Дети | ПО Сотрудник.Ссылка = Дети.Владелец.Ссылка |ГДЕ | Дети.Ссылка ЕСТЬ NULL | И Сотрудник.ЭтоГруппа = ЛОЖЬ" |
|||
13
zak555
04.09.11
✎
14:12
|
(8) оптимальность интересует
|
|||
14
zak555
04.09.11
✎
14:15
|
мне кажется, что (6) не оптимально
он будет "клеить" всех сотров и все детей.владельцев |
|||
15
zak555
04.09.11
✎
14:21
|
что-то типа того, но тут ошибка
ВЫБРАТЬ Сотрудник.Представление ИЗ Справочник.Сотрудники КАК Сотрудник ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ РАЗЛИЧНЫЕ Дети.Владелец.Ссылка ИЗ Справочник.Дети КАК Дети) КАК СотрудникиСДетьми ПО Сотрудник.Ссылка = СотрудникиСДетьми.Ссылка ГДЕ Сотрудник.Ссылка ЕСТЬ NULL И Сотрудник.ЭтоГруппа = ЛОЖЬ |
|||
16
kosts
04.09.11
✎
14:28
|
(15)
Но по сути тоже самое что и (12) |
|||
17
Alexandr Puzakov
04.09.11
✎
15:02
|
1 и 2 можно получить одним запросом ;)
(16) ахтунг! Зачем соединять с вложенным запросом-то? |
|||
18
Dmitrii
гуру
04.09.11
✎
15:26
|
(0) В первом запросе убери точкаСсылка
|
|||
19
Dmitrii
гуру
04.09.11
✎
15:29
|
+ к (18) да и во всех остальных тоже
|
|||
20
Dmitrii
гуру
04.09.11
✎
15:30
|
заменить "Сотрудник.ЭтоГруппа = ЛОЖЬ" на "(НЕ Сотрудник.ЭтоГруппа)"
|
|||
21
Fragster
гуру
04.09.11
✎
16:12
|
второй не оптимальный, надо левое соединение и отбор по null,
да и первый, если придираться - сгруппировать работает быстрее, чем РАЗЛИЧНЫЕ на больших выборках |
|||
22
acsent
04.09.11
✎
16:21
|
(21) сгруппировать работает быстрее, чем РАЗЛИЧНЫЕ на больших выборках - врешь
|
|||
23
ice777
04.09.11
✎
16:43
|
(22) а почему?
|
|||
24
zak555
04.09.11
✎
17:58
|
(16) запрос не работаеот
|
|||
25
zak555
04.09.11
✎
18:00
|
(17) > ахтунг! Зачем соединять с вложенным запросом-то?
так это не быстрее ? |
|||
26
zak555
04.09.11
✎
18:03
|
переправил (16) получил
"ВЫБРАТЬ | Сотрудник.Представление |ИЗ | Справочник.Сотрудники КАК Сотрудник | ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ РАЗЛИЧНЫЕ | Дети.Владелец КАК Ссылка | ИЗ | Справочник.Дети КАК Дети) КАК СотрудникиСДетьми | ПО Сотрудник.Ссылка = СотрудникиСДетьми.Ссылка |ГДЕ | СотрудникиСДетьми.Ссылка ЕСТЬ NULL | И (НЕ Сотрудник.ЭтоГруппа)" |
|||
27
zak555
04.09.11
✎
18:06
|
(18) (19) ага
(20) почему ? это быстрее или как ? |
|||
28
zak555
04.09.11
✎
18:06
|
(9) > В запросах 1С не рекомендуется использовать конструкцию "В", потому что не всегда делаются оптимальные планы.
где этот написано ? |
|||
29
CepeLLlka
04.09.11
✎
18:13
|
(5) Запрос итак тебе обойдёт все элементы.. а потом уже из них выберет только различные..
|
|||
30
kosts
04.09.11
✎
18:25
|
(28) На ИТС вроде читал
|
|||
31
Armando
04.09.11
✎
18:33
|
(30) не путаешь с "В ИЕРАРХИИ"?
|
|||
32
kosts
04.09.11
✎
18:36
|
(31) В ИЕРАРХИИ не заменить соединением, а там было что вместо "В" лучше использовать соединение.
|
|||
33
Alexandr Puzakov
04.09.11
✎
18:50
|
(25) это намного медленнее. Фирма 1С рекомендует избегать соединений с вложенными запросами и виртуальными таблицами (они тоже являются вложенными запросами, только формируются системой).
|
|||
34
Alexandr Puzakov
04.09.11
✎
18:57
|
+(33) разумеется, не на каждый случай. Основная причина, по которой стоит отказываться с соединением с вложенными запросами - велик риск ошибки СУБД в построении плана запроса. И самое главное, нужно учитывать прогноз количества элементов, которые будут в соединяемых таблицах: если в обоих таблицах прогнозируется несколько десятков или сотен строк, то можно смело соединять, а если же хотя бы в одной таблице будут десятки тысяч строк, то тады лучше избегать таких соединений...
|
|||
35
Alexandr Puzakov
04.09.11
✎
19:01
|
Например, если в справочнике сотрудники всего пара сотен элементов, ну и соответственно в справочнике детей тоже несколько сотен элементов, то можно смело соединять их через вложенный запрос, лишние 0.00сколькототам секунд погоды не изменят, а вот если это ИБ в каком-нить большом холдинге, то лучше так не баловаться...
|
|||
36
zak555
04.09.11
✎
19:11
|
(33) какой тогда вариант ?
|
|||
37
zak555
04.09.11
✎
19:17
|
*оптимальный
|
|||
38
Alexandr Puzakov
04.09.11
✎
19:20
|
(36) соединить таблицы
ПО Сотрудники.Ссылка = Дети.Владелец при таком соединении будут задействованы готовые индексы. |
|||
39
zak555
04.09.11
✎
19:22
|
(38) а если бы не в 1с это писать ?
|
|||
40
Alexandr Puzakov
04.09.11
✎
19:23
|
У справочника-владельца есть индекс
[Ссылка] у подчиненного справочника есть индексы [Владелец]+[Код]+[Ссылка] вот по этим индексам оно и соединится оптимально. |
|||
41
Alexandr Puzakov
04.09.11
✎
19:23
|
(39) я х. з. Зависит от СУБД.
|
|||
42
zak555
04.09.11
✎
19:28
|
(41) sql | mySQL ?
|
|||
43
zak555
04.09.11
✎
19:29
|
(40) тупо левое соединение владельца с дети.владелец и оттуда смотреть НУЛЛ?
|
|||
44
Alexandr Puzakov
04.09.11
✎
19:35
|
(43) да!
|
|||
45
Alexandr Puzakov
04.09.11
✎
19:36
|
(42) ну в рекомендациях как раз описано применительно к SQL Server.
|
|||
46
zak555
04.09.11
✎
19:38
|
(45) а где они эти рекомендации ?
|
|||
47
zak555
04.09.11
✎
19:39
|
(44) ладно
пусть владельцев 10 000 у каждого по 50 000 детей всё равно такой же запрос писать ? |
|||
48
Alexandr Puzakov
04.09.11
✎
19:39
|
||||
49
Alexandr Puzakov
04.09.11
✎
19:41
|
(47) желательно. Если очень-очень хочется, то можно и через вложенный запрос, но может получиться не айс...
|
|||
50
zak555
04.09.11
✎
19:42
|
(48) что нужно для доступа ?
|
|||
51
Alexandr Puzakov
04.09.11
✎
19:43
|
(50) очевидно, логин и пароль...
|
|||
52
zak555
04.09.11
✎
19:43
|
(51) ИТС подписки 7
|
|||
53
Alexandr Puzakov
04.09.11
✎
19:47
|
(52) не-а. Отдельные, как на доступ в партнерскую конференцию. На диске ИТС есть то же самое:
Технологическая поддержка > Методическая поддержка 1С 8 > Технологические вопросы крупных внедрений > типичные причины неоптимальной работы запросов и методы оптимизации |
|||
54
Alexandr Puzakov
04.09.11
✎
19:49
|
И все на том же диске стоит почитать:
Технологическая поддержка > Методическая поддержка 1С 8 > Методические рекомендации по конфигурированию > Язык запросов |
|||
55
zak555
04.09.11
✎
20:17
|
(54) что-то там про индексы нет
|
|||
56
Alexandr Puzakov
04.09.11
✎
20:44
|
||||
57
zak555
04.09.11
✎
20:45
|
(56) почитаем =)
|
|||
58
Alexandr Puzakov
04.09.11
✎
20:46
|
На диске ИТС статья "Индексы таблиц базы данных", только вот я не помню, в каком разделе она находится, но можно через поиск найти.
|
|||
59
zak555
04.09.11
✎
20:47
|
ещё вопрос :
на ИТС есть пример внутреннего соединения : ВЫБРАТЬ ДокТовары.Номенклатура, Спр.Артикул, ДокТовары.Количество, ДокТовары.Сумма ИЗ Справочник.Номенклатура КАК Спр СОЕДИНЕНИЕ Документ.АвансовыйОтчет.Товары КАК ДокТовары ПО Спр.Ссылка = ДокТовары.Номенклатура это будет тоже самое и с такой же скоростью выполняться, как ВЫБРАТЬ ДокТовары.Номенклатура, Спр.Артикул, ДокТовары.Количество, ДокТовары.Сумма ИЗ Справочник.Номенклатура КАК Спр, Документ.АвансовыйОтчет.Товары КАК ДокТовары ГДЕ Спр.Ссылка = ДокТовары.Номенклатура |
|||
60
zak555
04.09.11
✎
20:57
|
это вопрос как бы
|
|||
61
zak555
04.09.11
✎
21:01
|
результат тот же
а вот скорость как замерить |
|||
62
CepeLLlka
04.09.11
✎
21:08
|
ЗАК... слушай.. а есть что-нибудь такое по типа СП только для языка запросов? Не поделишься?
|
|||
63
zak555
04.09.11
✎
21:24
|
(62) да хоть http://base.vingrad.ru/view/2871-Osnovyi-yazyika-SQL
|
|||
64
ДенисЧ
04.09.11
✎
21:29
|
(59) 1с сделает это одинаковым.
|
|||
65
CepeLLlka
04.09.11
✎
21:48
|
(63) Так это ж про SQL запросы.. а я про 1С спрашивал же :(
|
|||
66
cViper
04.09.11
✎
22:00
|
(59) В первом случае будет быстрее.
|
|||
67
cViper
04.09.11
✎
22:01
|
+(66) Во втором случае он сделает декартово произведение, а потом наложит учловие "ГДЕ".
|
|||
68
zak555
04.09.11
✎
23:00
|
(64) тогда зачем два варианта ?
|
|||
69
zak555
04.09.11
✎
23:00
|
(65) тоже самое
|
|||
70
zak555
04.09.11
✎
23:01
|
(66) обоснование
(67) внутренне соединение это что такое по-твоему ? я всегда думал, что это декартовое произведение, а потом фильтр |
|||
71
cViper
04.09.11
✎
23:08
|
(70) Внутреннее соединение - берутся все значения левого множества у которых есть соответствие из правого множества.
|
|||
72
cViper
04.09.11
✎
23:09
|
+(71)
Для декартова произведения не надо вообще писать ключевое слово "соединение". Просто в "ИЗ" указываешь 2 таблицы через запятую и каждой строке левого множество будет соответствовать каждая строка правого множества. |
|||
73
cViper
04.09.11
✎
23:12
|
+(72) В SQL есть CROSS JOIN.
|
|||
74
zak555
04.09.11
✎
23:59
|
(71) да, согласен
Внутренние соединения Внутренние соединения - самый распространённый тип соединений. Внутреннее соединение просто находит пары строк, которые соединяются и удовлетворяют предикату соединения. Например, показанный ниже запрос использует предикат соединения "S.Cust_Id = C.Cust_Id", позволяющий найти все продажи и сведения о клиенте с одинаковыми значениями Cust_Id: select * from Sales S inner join Customers C on S.Cust_Id = C.Cust_Id |
|||
75
zak555
05.09.11
✎
13:01
|
нужно проверять на данных
надо в БД забить 1 000 000 детей |
|||
76
Alexandr Puzakov
05.09.11
✎
13:29
|
(75) что мешает?
|
|||
77
Axel2009
05.09.11
✎
13:36
|
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Дети.Владелец |ИЗ | Справочник.Дети КАК Дети" самое оптимальное - так. будет проверяться 1 индекс и вывод его. без доп чтений. а все остальное будет тормозом. запрос "В" может свалится в "или" и будете иметь реальные тормоза. |
|||
78
Axel2009
05.09.11
✎
13:38
|
(67) планы то сравнивал? чтобы такое говорить?
|
|||
79
Axel2009
05.09.11
✎
13:41
|
(21) различные и сгруппировать - монопенисуальные операции если план смотреть..
|
|||
80
VVi3ard
05.09.11
✎
14:00
|
По 2рому запросу в данном случае наверное разницы нет так как объемы маленькие но в целом лучше использовать временную таблицу и пакет запроса.
1. Формируем ВТ: ВТСотрудникиСДетьми, добавляем индекс по "ССылка". 2. К "Справочник.Сотрудники" левым соединением присоединяем ВТСотрудникиСДетьми в где пишем условие ВТСотрудникиСДетьми.Ссылка ЕСТЬ NULL ну и другие по желанию. |
|||
81
Fragster
гуру
05.09.11
✎
14:04
|
(22) при выборке одного поля по индексу - да. иначе - нет
|
|||
82
VVi3ard
05.09.11
✎
14:06
|
(33) "Это намного медленнее. Фирма 1С рекомендует избегать соединений с вложенными запросами и виртуальными таблицами (они тоже являются вложенными запросами, только формируются системой)".
Ну с Вложенными запросами понятно, на момент выполнения запроса SQL ничего не знает о количестве записей в результате вложенного запроса, и с индексами тоже нет определенности поэтому запрос может выполнятся не оптимально. А в чем проблема при соединении с ВременымиТаблицами? |
|||
83
kuza2000
05.09.11
✎
14:15
|
(0)
Не совсем корректно поставлено вопрос, поскольку SQL - это декларативный язык, а не процедурный. Понятие эффективности лучше всего относить к плану исполнения запроса в применении к конкретным данным. Один и тот же текст запроса может транслироваться в план огромным числом способов в-зависимости от большого числа факторов. И наоборот - разные запросы могут порождать один и тот же план. Пример. Есть два запроса. Первый: ВЫБРАТЬ Таб1.* ИЗ Таб1 ВНУТРЕННЕЕ СОЕДИНЕНИЕ Таб2 ПО Таб1.Поле = Таб2.Поле Второй: ВЫБРАТЬ Таб1.* ИЗ Таб1 ГДЕ Таб1.Поле В (ВЫБРАТЬ Таб2.Поле ИЗ Таб2) Вроде бы разные запросы, но на MS SQL план исполнения обоих у меня получался совершенно одинаков. Не похож, а именно совершенно одинаков. Поэтому, что бы узнать точно, что будет эффективнее - путь только один. Пробовать на конкретных данных и анализировать план исполнения. Но общее правило такое - запросы должны быть максимально просты, что бы оптимизатор "понял" их и сгенерировал оптимальный план. Отвечая на вопрос - я бы использовал такие запросы: Первый. ВЫБРАТЬ РАЗЛИЧНЫЕ Владелец ИЗ Дети Второй. ВЫБРАТЬ РАЗЛИЧНЫЕ Сотрудники.Ссылка ИЗ Сотрудники ЛЕВОЕ СОЕДИНЕНИЕ Дети ПО Сотрудники.Ссылка = Дети.Владелец ГДЕ Дети.Владелец ЕСТЬ NULL В общем, пробуем и смотрим план! :) |
|||
84
VVi3ard
05.09.11
✎
14:18
|
Кстати (17) тоже прав может быть в данном случае выгоднее будет сразу левым соединением без ВТ соединить, но если нужно одновременно получать эти данные то пакеты будут оптимальней.
|
|||
85
kuza2000
05.09.11
✎
14:19
|
+ (83) Во втором нужно, конечно, условие еще на группы поставить
|
|||
86
kuza2000
05.09.11
✎
14:21
|
(0) Кстати, первый запрос такой и предложен был, только .Ссылка надо убрать, иначе может быть лишнее неявное соединение :)
|
|||
87
Axel2009
05.09.11
✎
14:34
|
(81) планы в студию где "иначе нет"
|
|||
88
Axel2009
05.09.11
✎
14:35
|
(83) " Вроде бы разные запросы, но на MS SQL план исполнения обоих у меня получался совершенно одинаков. Не похож, а именно совершенно одинаков. Поэтому, что бы узнать точно, что будет эффективнее - путь только один. Пробовать на конкретных данных и анализировать план исполнения. "
повезло. |
|||
89
VVi3ard
05.09.11
✎
14:36
|
(83) Я вообще не понимаю зачем использовать конструкцию В (Выбрать .... ) всегда надо в этом случае делать внутренее соединение.
Не В(Выбрать ) я ещё могу понять. |
|||
90
Fragster
гуру
05.09.11
✎
14:37
|
(89) отбор в параметрах виртуальной таблицы
|
|||
91
Axel2009
05.09.11
✎
14:38
|
(89) ты не умеешь их готовить.
|
|||
92
Fragster
гуру
05.09.11
✎
14:43
|
(87) очень просто:
берешь Выбрать * Из Справочник.Номенклатура, открываешь конструктором, удаляешь поле Ссылка (ну и ТЧ, если есть). 1 вариант - получившегося запроса меряешь с Различные, другой - с Группировать. У меня получилось с Различные 2.2 секунды, с Группировать - 0.2 на 10к элементов справочника номенклатуры |
|||
93
Axel2009
05.09.11
✎
14:57
|
(92) а второй раз с Различные?
|
|||
94
kuza2000
05.09.11
✎
14:58
|
(77) согласен, даже в таблицу не полезет
|
|||
95
Fragster
гуру
05.09.11
✎
15:05
|
(93) после нескольких выполнений картина более-менее выровнялась, но все равно:
Название таблицы Время подзапроса Количество строк РАЗЛИЧНЫЕ1 0,5 10 080 СГРУППИРОВАТЬ1 0,485 10 080 РАЗЛИЧНЫЕ2 0,547 10 080 СГРУППИРОВАТЬ2 0,328 10 080 |
|||
96
Fragster
гуру
05.09.11
✎
15:05
|
разница, очевидно, в пользу Сгруппировать
|
|||
97
Fragster
гуру
05.09.11
✎
15:07
|
более того, даже если тупо выбирать .Ссылка - все равно ~15% в пользу Сгруппировать
|
|||
98
Axel2009
05.09.11
✎
15:14
|
(97) не везет твоим различным что могу сказать. у меня в обратку чаще. сгруппировать дольше чем различные..
|
|||
99
Axel2009
05.09.11
✎
15:16
|
(98)+в общем я сравнивал планы. они идентичны. поэтому время зависит от загрузки сервака и прочее прочее
|
|||
100
Дукат
05.09.11
✎
15:18
|
100! =)
|
|||
101
Stim213
05.09.11
✎
15:18
|
черт((
|
|||
102
Дукат
05.09.11
✎
15:19
|
(101) шо таки?
|
|||
103
Fragster
гуру
05.09.11
✎
15:20
|
нда, у меня таки тенденция:
получает Название таблицы Время подзапроса Количество строк СГРУППИРОВАТЬ1 10,797 1 409 449 РАЗЛИЧНЫЕ1 10,921 1 409 449 РАЗЛИЧНЫЕ2 11,358 1 409 449 СГРУППИРОВАТЬ2 10,948 1 409 449 |
|||
104
Fragster
гуру
05.09.11
✎
15:20
|
хоть чуть-чуть, но сгруппировать быстрее :)
|
|||
105
Aprobator
05.09.11
✎
15:25
|
условие можно написать так (НЕ Сотрудник.ЭтоГруппа) - впрочем это дело вкуса.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |