| Начало » Использование СУБД » Firebird, HQbird, InterBase » Изменения оптимизатора? Переход к форуму:
	| 
		
			| Изменения оптимизатора? [сообщение #140] | Tue, 05 July 2022 19:55  |  
			| 
				
				
					|  optimiz94 Сообщений: 15
 Зарегистрирован: July 2022
 | Junior Member |  |  |  
	| Есть такой запрос: 
 
 На все поля, перечисленные в where, есть индексы (точнее, foreign keys, а индексы уже следствие).select m.Id
from Items_Main m
left join Items_Ext e on e.Id=m.Id
where m.f0=?p0
and e.f1=?p1
and e.f2=?p2
and e.f3=?p3
and e.f4=?p4
 Раньше FB использовал индекс по m.f0, и не мог использовать индексы по таблице e, потому что она была в left join. Теперь может, и это ломает планы. По полям f0 и f1 хорошая селективность, но оптимизатор использует не просто индекс по f1, а пересечение индексов по f1 и f2. Пересечение индексов наверное хорошая вешь для аналитических запросов, но для быстрых OLTP это просто беда, нужно всегда следить, чтобы такого не случилось.
 В моём случае нужно переписать запрос как
 
 Я думал, что это хорошая идея делать left join, чтобы исключить использование индексов (этот же трюк и в SQL Server работает). Теперь придётся видимо так делать:where m.f0=?p0 and e.f1=?p1 and e.f2+0=?p2 and e.f3+0=?p3 and e.f4+0=?p4
 Изменение произошло где-то между WI-V3.0.8.33392 и WI-V3.0.8.33540.left join Items_Ext e on e.Id=m.Id+0Это значит, при переезде с FB3 на FB4 может много чего полететь.
 
 |  
	|  |  |  
	|  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #142 является ответом на сообщение #141] | Tue, 05 July 2022 20:40   |  
			| 
				
				
					|  optimiz94 Сообщений: 15
 Зарегистрирован: July 2022
 | Junior Member |  |  |  
	| Пересечение индексов очень медленная операция. Она оправдана, когда запрос возвращает миллионы строк.
 Если запрос возвращает 1-2 строки, а нужно прочитать целиком пару индексов в огромных таблицах, это плюс 2-5 секунд к выполнению (против сотен миллисекунд при использовании одного индекса). Под нагрузкой супер-критично.
 
 Впрочем, я проверил на более свежей версии WI-V3.0.10.33587 - вернули старое поведение.
 Это был баг?
 [Обновления: Tue, 05 July 2022 20:41] Известить модератора |  
	|  |  |  
	|  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #151 является ответом на сообщение #148] | Thu, 07 July 2022 15:00   |  
			| 
				
				
					|  optimiz94 Сообщений: 15
 Зарегистрирован: July 2022
 | Junior Member |  |  |  
	| m7m писал(а) Thu, 07 July 2022 08:07 Это неверное утверждение/вывод, ну по крайней мере вторая часть "не мог использовать индексы по таблице e"Ну я всегда использовал left join как hint оптимизатору "не использовать индексы на этой таблице" (кроме индекса по полю join, разумеется). 
 Можете на своих базах воспроизвести пример, когда индекс применяется в этом случае?
 
 Вот мой пример: две огромные таблицы Items_Main и Items_Ext, параллельно связаны по полю Id.
 В запросе
 
 Используется ужасно медленный план с полным сканом первой таблицы, хотя по индексу на второй таблице моментально выбралась бы ровно одна записьselect m.Id
from Items_Main m
left join Items_Ext e on e.Id=m.Id
where e.f1=?p1
 PLAN JOIN (M NATURAL, E INDEX (PK_ITEMS_EXT))[Обновления: Thu, 07 July 2022 15:02] Известить модератора |  
	|  |  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #152 является ответом на сообщение #151] | Fri, 08 July 2022 09:35   |  
			| 
				
				
					|  m7m Сообщений: 19
 Зарегистрирован: June 2022
 Географическое положение: Мариуполь,Укр...
 | Junior Member |  |  |  
	| >>Ну я всегда использовал left join как hint оптимизатору "не использовать индексы на этой таблице" (кроме индекса по полю join, разумеется). >>Можете на своих базах воспроизвести пример, когда индекс применяется в этом случае?
 Не могу, ибо именно про индексы по join я и имел ввиду
 ---------------
 
 Блин я тебя не понимаю, откуда для запроса
 
 может появиться  планselect m.Id
from Items_Main m
left join Items_Ext e on e.Id=m.Id
where e.f1=?p1
 ты ж не накладываешь никаких ограничений на Items_Main mPLAN JOIN (M INDEX (.....), E INDEX (PK_ITEMS_EXT))
 Более того этот запрос, в данном случае эквивалентен запросу
 
 который будет наверное эффективней чем исходныйselect m.Id
from Items_Main m
join Items_Ext e on e.Id=m.Id
where e.f1=?p1
и план наверное будет где-то такой
 
 или я вообще не понимаю, о чем речьPLAN JOIN (E INDEX (.....), M  INDEX (.....))
 
 |  
	|  |  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #156 является ответом на сообщение #152] | Fri, 08 July 2022 19:04   |  
			| 
				
				
					|  optimiz94 Сообщений: 15
 Зарегистрирован: July 2022
 | Junior Member |  |  |  
	| В WI-V3.0.8.33540 для запроса 
 появился план примерно такой (пишу по памяти, версию уже обновили и доступа у меня к ней нет. могу где-то опечататься, но в целом так)select m.Id
from Items_Main m
left join Items_Ext e on e.Id=m.Id
where m.f0=?p0
and e.f1=?p1
and e.f2=?p2
and e.f3=?p3
and e.f4=?p4
 и это стало большой проблемой.PLAN JOIN (E INDEX (FK_ITEMS_EXT_REF_F1, FK_ITEMS_EXT_REF_F2), M INDEX (PK_ITEMS_MAIN))
 То есть, сервер никогда не использовал индексы по таблице, подключенной через left join, и вдруг начал.
 [Обновления: Fri, 08 July 2022 19:16] Известить модератора |  
	|  |  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #157 является ответом на сообщение #152] | Fri, 08 July 2022 19:11   |  
			| 
				
				
					|  optimiz94 Сообщений: 15
 Зарегистрирован: July 2022
 | Junior Member |  |  |  
	| m7m писал(а) Fri, 08 July 2022 09:35 Да, эквивалентен, но оптимизатор не умеет его делать если таблица, по которой хороший индекс, приджойнена через left join.Более того этот запрос, в данном случае эквивалентен запросу ... который будет наверное эффективней чем исходный
 и план наверное будет где-то такой
 
 PLAN JOIN (E INDEX (.....), M  INDEX (.....))
 Если считаете, что умеет, покажите тестовый скрипт (создать пару табличек, накидать пару тысяч записей и посмотреть план запроса) - у меня такое не выходит.
 
 Если left join заменить на inner join - тогда да, оптимизатор начинает использовать хороший индекс по E.
 |  
	|  |  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #158 является ответом на сообщение #156] | Fri, 08 July 2022 22:31   |  
			| 
				
				
					|  m7m Сообщений: 19
 Зарегистрирован: June 2022
 Географическое положение: Мариуполь,Укр...
 | Junior Member |  |  |  
	| optimiz94 писал(а) Fri, 08 July 2022 19:04 В WI-V3.0.8.33540 для запросаДля этого запроса план более чем странный
 появился план примерно такой (пишу по памяти, версию уже обновили и доступа у меня к ней нет. могу где-то опечататься, но в целом так)select m.Id
from Items_Main m
left join Items_Ext e on e.Id=m.Id
where m.f0=?p0
and e.f1=?p1
and e.f2=?p2
and e.f3=?p3
and e.f4=?p4
 и это стало большой проблемой.PLAN JOIN (E INDEX (FK_ITEMS_EXT_REF_F1, FK_ITEMS_EXT_REF_F2), M INDEX (PK_ITEMS_MAIN))
 То есть, сервер никогда не использовал индексы по таблице, подключенной через left join, и вдруг начал.
  
 
 |  
	|  |  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #159 является ответом на сообщение #157] | Fri, 08 July 2022 22:43   |  
			| 
				
				
					|  m7m Сообщений: 19
 Зарегистрирован: June 2022
 Географическое положение: Мариуполь,Укр...
 | Junior Member |  |  |  
	| optimiz94 писал(а) Fri, 08 July 2022 19:11 m7m писал(а) Fri, 08 July 2022 09:35Судя по тексту запросаДа, эквивалентен, но оптимизатор не умеет его делать если таблица, по которой хороший индекс, приджойнена через left join.Более того этот запрос, в данном случае эквивалентен запросу ... который будет наверное эффективней чем исходный
 и план наверное будет где-то такой
 
 PLAN JOIN (E INDEX (.....), M  INDEX (.....))
 Если считаете, что умеет, покажите тестовый скрипт (создать пару табличек, накидать пару тысяч записей и посмотреть план запроса) - у меня такое не выходит.
 
 Если left join заменить на inner join - тогда да, оптимизатор начинает использовать хороший индекс по E.
 
 тебе left join совершенно не нужен, и  пожалуй даже вреденselect m.Id
from Items_Main m
left join Items_Ext e on e.Id=m.Id
where m.f0=?p0
and e.f1=?p1
and e.f2=?p2
and e.f3=?p3
and e.f4=?p4и я не понимаю упорного желания его использовать ибо он по результатам совершенно эквивалентен запросу
 
 который дает волю оптимизатору построить оптимальный с его точки зрения планselect m.Id
from Items_Main m
join Items_Ext e on e.Id=m.Id
where m.f0=?p0
and e.f1=?p1
and e.f2=?p2
and e.f3=?p3
and e.f4=?p4И при этом если по каким-то причинам надо ограничить его свободу в использовании индексов
 то заставить оптимизатор не использовать индекс можно как-то так  e.f1+0=?p1
 |  
	|  |  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #160 является ответом на сообщение #159] | Sat, 09 July 2022 01:20   |  
			| 
				
				
					|  optimiz94 Сообщений: 15
 Зарегистрирован: July 2022
 | Junior Member |  |  |  
	| m7m, я не прошу помочь с написанием запроса. Я здесь, чтобы обсудить факт - поведение оптимизатора существенно менялось, и возможно разработчики СУБД что-то скажут по этому поводу: это временный сбой был, или в будущих версиях они введут эту (в принципе, корректную) оптимизацию, и надо это иметь ввиду.
 
 Также я зацепился за утверждение:
 m7m писал(а) Thu, 07 July 2022 08:07
 >>Раньше FB использовал индекс по m.f0, и не мог использовать индексы по таблице eЕсли у вас такое на практике встречалось, прошу посмотреть - повторяется ли оно сейчас. Но я уже понимаю, что вы похоже просто теоретизировали.Это неверное утверждение/вывод, ну по крайней мере вторая часть "не мог использовать индексы по таблице e"
 |  
	|  |  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #161 является ответом на сообщение #160] | Sat, 09 July 2022 07:22   |  
			| 
				
				
					|  m7m Сообщений: 19
 Зарегистрирован: June 2022
 Географическое положение: Мариуполь,Укр...
 | Junior Member |  |  |  
	| optimiz94 писал(а) Sat, 09 July 2022 01:20 Я уже ответил на это:Также я зацепился за утверждение:
 m7m писал(а) Thu, 07 July 2022 08:07
 >>Раньше FB использовал индекс по m.f0, и не мог использовать индексы по таблице eЕсли у вас такое на практике встречалось, прошу посмотреть - повторяется ли оно сейчас. Но я уже понимаю, что вы похоже просто теоретизировали.Это неверное утверждение/вывод, ну по крайней мере вторая часть "не мог использовать индексы по таблице e"
 >>Ну я всегда использовал left join как hint оптимизатору "не использовать индексы на этой таблице" (кроме индекса по полю join, разумеется).
 >>Можете на своих базах воспроизвести пример, когда индекс применяется в этом случае?
 Не могу, ибо именно про индексы по join я и имел ввиду
 
 И таки да я  теоретизировал, и продолжаю это делать
 [Обновления: Sat, 09 July 2022 07:44] Известить модератора |  
	|  |  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #162 является ответом на сообщение #160] | Sat, 09 July 2022 07:38   |  
			| 
				
				
					|  m7m Сообщений: 19
 Зарегистрирован: June 2022
 Географическое положение: Мариуполь,Укр...
 | Junior Member |  |  |  
	| optimiz94 писал(а) Sat, 09 July 2022 01:20 m7m, я не прошу помочь с написанием запроса.Да я и не помогаю, я для себя пытаюсь понять задлянафига такое делать.Я здесь, чтобы обсудить факт - поведение оптимизатора существенно менялось, и возможно разработчики СУБД что-то скажут по этому поводу: это временный сбой был, или в будущих версиях они введут эту (в принципе, корректную) оптимизацию, и надо это иметь ввиду.
 
 select m.Id
 from Items_Main m
 left join Items_Ext e on e.Id=m.Id
 where m.f0=?p0
 and e.f1=?p1
 and e.f2=?p2
 and e.f3=?p3
 and e.f4=?p4
 
 Сочетание left join и условие в where на ведомую таблицу в моей голове не укладывается
 |  
	|  |  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #163 является ответом на сообщение #162] | Sat, 09 July 2022 11:37   |  
			| 
				
				
					|  optimiz94 Сообщений: 15
 Зарегистрирован: July 2022
 | Junior Member |  |  |  
	| m7m писал(а) Sat, 09 July 2022 07:38 Да я и не помогаю, я для себя пытаюсь понять задлянафига такое делать. Сочетание left join и условие в where на ведомую таблицу в моей голове не укладывается
 В этой схеме данных такая специфика, что по полю f0 очень высокая селективность, во всей таблице M для любого значения выберется в пределах 10 строк (F0 это номер заказа), а по полям F1-F4 так себе селективность (это номенклатура). Поэтому я поставил left join, чтобы оптимизатор никогда не использовал индексы по E.select m.Id
from Items_Main m
left join Items_Ext e on e.Id=m.Id
where m.f0=?p0
and e.f1=?p1
and e.f2=?p2
and e.f3=?p3
and e.f4=?p4
 А тот запрос, который вызвал ваше недоумение
 
 это попытка в чистом виде выделить проблему.select m.Id
from Items_Main m
left join Items_Ext e on e.Id=m.Id
where e.f1=?p1[Обновления: Sat, 09 July 2022 11:46] Известить модератора |  
	|  |  |  
	|  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #182 является ответом на сообщение #166] | Thu, 14 July 2022 11:17   |  
			| 
				
				
					|  optimiz94 Сообщений: 15
 Зарегистрирован: July 2022
 | Junior Member |  |  |  
	| Спасибо за ответ. 
 >> 1. Оптимизатор всегда мог использовать индексы полей в условии соединения left join
 
 Я понимаю, что в операторе
 
 используется индекс по e.Idleft join e on e.Id = m.Id
 Вопрос этого топика в том, может ли в конструкции
 
 использоваться индекс по e.f1left join e on e.Id = m.Id
where e.f1 = ?f1У меня ни на каких версиях не получалось
 Кроме одной странной, с которой я начал топик - изменения в ней настораживают.
 
 
 >> 2. Использовать left join как подсказку есть глупость
 
 Понятно, но раньше отключение индексов хинтом 'left join' всегда работало.
 Буду потихоньку переписывать на +0
 
 >>  Кстати есть наработки которые превращают такие left в inner join.
 
 Видимо, я на такую наработку и нарвался.
 Такое надо осторожно менять, потому что может много систем сломать в проде.
 
 
 Кстати, есть ещё досадный баг с left join. В запросе
 
 работает индекс по e.F1select *
from Items_Main m
join Items_Ext e on e.Id=m.Id
where e.F1 = ?f1
 А в запросе
 
 индекс уже не работает, планselect *
from Items_Main m
left join Users u on u.UserId=m.UserId
join Items_Ext e on e.Id=m.Id
where e.F1 = ?f1PLAN JOIN (JOIN (M NATURAL, U INDEX (PK_USERS)), E INDEX (PK_ITEMS_EXT))
 
 А вот так - все в порядке
 
 
 PLAN JOIN (JOIN (E INDEX (FK_ITEMS_EXT_REF_F1), M INDEX (PK_ITEMS_MAIN)), U INDEX (PK_USERS))select *
from Items_Main m
join Items_Ext e on e.Id=m.Id
left join Users u on u.UserId=m.UserId
where e.F1 = ?f1
 В автоматизированных конструкторах запросов, которые я сам пишу, я это учитываю, и все left join переставляю в конец. Геморой, но что поделать.
 Но со всякими чужими ORM, которые сами создают запросы - беда.
 Какие только извращения не приходится выдумывать, чтобы обойти этот баг.
 
 
 >> И да "left join e ... where e. ..." вызывает недоумение
 
 Зачем я так сделал, подробно написал в предыдущем посте: я полагался на то, что план будет построен вокруг индекса по m.F0, а условие по полю e.F1 будет обрабатываться не через индекс.
 
 Сейчас переписал на +0 обращения к тем полям, по которым я не хочу использовать индекс.
 
 
 [Обновления: Thu, 14 July 2022 11:35] Известить модератора |  
	|  |  |  
	|  |  
	|  |  
	|  |  
	|  |  
	| 
		
			| Re: Изменения оптимизатора? [сообщение #206 является ответом на сообщение #192] | Tue, 19 July 2022 14:32   |  
			| 
				
				
					|  optimiz94 Сообщений: 15
 Зарегистрирован: July 2022
 | Junior Member |  |  |  
	| kdv писал(а) Mon, 18 July 2022 03:09 не вижу ничего необычного в последних двух планах. left/right всегда выполняются строго "попарно". Поэтому оптимизатор сначала делает left, а потом делает inner. Если же вначале стоят inner, то у оптимизатора уже есть некая свобода действий. Но это какие-то внутренние заморочки движка. У MS SQL Server нет этой проблемы.А plan m natural потому что m left join, а дальше идет только условие объединения и фильтрация по e. Сервер никак тут не может использовать индексы по m, просто некуда. А left означает "взять все записи слева". Ну и ...
 Вручную это всё можно учитывать и переставлять join-ы местами.
 Но вот с ORM такой гибкости нет, приходится либо разбивать на несколько запросов, либо извращаться.
 
 Например, на задачу "достань мне все заказы пользователей из Владивостока", ORM сделает запрос с планом (O NATURAL).
 
 Приходится переформулировать как "достань мне город Владивосток и зафетчи его заказы"select ...
from Orders o
left join ... опциональные расширения к заказу в схеме данных
join Cities c on c.Id=o.CityId
where c.Id=?pCity
 dimitr писал(а) Mon, 18 July 2022 08:45
 По-моему, топикстартер забыл нам сказать, что у него не совсем Firebird... а на самом деле HQbirdДумал, будет понятно из номеров версий публичных релизов. 
 [Обновления: Tue, 19 July 2022 15:24] Известить модератора |  
	|  |  |  
	|  |  
	|  |  
	|  | 
 
 
 Текущее время: Fri Oct 31 07:47:30 GMT+3 2025 
 Общее время, затраченное на создание страницы: 0.01250 секунд |