Чрезмерная оптимизация кода. Проблемы производительности

29.05.23

База данных - HighLoad оптимизация

Рассмотрим ситуацию, когда излишняя оптимизация приводит к неочевидным проблемам.

Продолжаем серию статей по вопросам оптимизации производительности. В этот раз у нас один интересный случай, который по праву заслуживает пристального рассмотрения.

Оптимизация в данном примере возведена в абсолют абсурд, по моему скромному мнению. Давайте рассмотрим данный пример, который мне подкинул коллега разработчик. Скажем спасибо Светлане, она сделала мой день) возможно, и Ваш тоже.

Мы рассмотрим эту проблему в классическом подходе:

  • Выявление проблемы
  • Объяснение ситуации
  • Поиск решения

 

I) Выявление проблемы.

 

Как было сказано выше, то с данной ситуацией столкнулся разработчик. Он выполнял перенос изменений из одной версии ERP 2.4 в новую 2.5. И при попытке проверить решение на рабочем примере увидел неожиданное поведение платформы - база зависала. Конечно же она работала, но выглядело это не очень обнадеживающе.

Давайте найдем точку возникновения проблемы. Примерная позиция нам известна, но как говорится точность позволяет повысить скорость решения проблемы. Открываем нашу конфигурацию мониторинга производительности и ищем долгие запросы. Этот запрос виден сразу, он один единственный длительностью более 6 тысяч секунд.

 

 

На рисунке мы видим, что во временную таблицу помещается почти 11 миллионов строк. Как мне рассказал разработчик, то таблица товаров в тестируемом документе содержала около 1000 строк. Обратите внимание, что специалисты нашей команды проверяют не на 2-3х строчках, а с достаточным количеством данных. Если бы мы тестировали тяп-ляп, то этой проблемы не обнаружили.

Ниже приведен контекст рассматриваемой ситуации.

 

 

 
 Контекст


 Сам запрос в представлении языка SQL выглядит следующим образом:

 

 

 
 Представление запроса SQL из технологического журнала


А вот это мы поймали в журнале СУБД Postgres. Тоже самое, но с текстовым планом запроса. Этот запрос мы чуть позже посмотрим в графическом представлении.

 
 Текст журнала событий СУБД Postgres

 

Теперь откроем код конфигурации и посмотрим что под капотом. Это модуль менеджера документа "Корректировка назначения товаров" -> функция ТаблицаПомещенияЯчейкиПоТоварам.

 
 Код функции ТаблицаПомещенияЯчейкиПоТоварам ERP 2.5

 

В этой функции большой пакетный запрос. И мы видим, что это один из запросов пакета. Давайте преобразуем текст SQL запроса в представления 1С и определим виновника данной ситуации (используем обработку - Конвертер для преобразования текстов запросов и планов SQL в представления языка 1С ):

 

 

Под этот отпечаток подходит следующий запрос из пакета:

 
 Запрос виновник

 

	;
	////////////////////////////////////////////////////////////////////////////////
	ВЫБРАТЬ РАЗЛИЧНЫЕ
		Таблица.Назначение КАК Назначение,
		Таблица.Номенклатура КАК Номенклатура,
		Таблица.Характеристика КАК Характеристика,
		Ячейки.Ссылка КАК Ячейка
	ПОМЕСТИТЬ ТоварыВЯчейкахОтбор
	ИЗ
		ВтТоварыЗаказа КАК Таблица
			ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.СкладскиеЯчейки КАК Ячейки
			ПО Ячейки.Владелец = Таблица.Склад
			ВНУТРЕННЕЕ СОЕДИНЕНИЕ СкладыИПомещения КАК СкладыИПомещения
			ПО СкладыИПомещения.Помещение = Ячейки.Помещение
				И СкладыИПомещения.Склад = Ячейки.Владелец
	ГДЕ
		ЕСТЬNULL(Таблица.Назначение.ДвиженияПоСкладскимРегистрам, ИСТИНА)
			И СкладыИПомещения.ИспользоватьАдресноеХранение
	ИНДЕКСИРОВАТЬ ПО
		Назначение, Номенклатура, Характеристика, Ячейка
	;
	////////////////////////////////////////////////////////////////////////////////

 

 

Мы нашли проблемную точку, продолжаем анализ этой проблемы и переходим к следующей части.

 

II) Анализ текущей ситуации.

 

Давайте преобразуем план запроса и посмотрим его графическое представление с помощью обработки конвертора SQL в 1С. Готовую схему запроса можно посмотреть по следующей ссылке:

https://explain.tensor.ru/archive/explain/a361999e59afee1396450cc2de78405f:0:2023-03-29#visio

Проанализируем представленный план запроса и посмотрим где проблема и что можно с этим сделать. Как мы видим на рисунке ниже происходит следующая ситуация. Будем двигаться слева на право и сверху вниз:

  • Изначально соединяется временная таблица товаров с назначениями, вопросов к такому соединению у меня нет;
  • Затем происходит соединение таблицы складских ячеек с таблицей "товары + назначения" (результат первого шага). Условие соединения по владельцу ячейки (это склад) и склада из предыдущей таблицы. Вот тут на картинке с выделенной позицией 1 показана первая проблема. На каждую строку таблицы товаров присоединяется порядка 12 тысяч записей таблицы ячеек. В результате перемножения 11 611*932 мы получаем 10 821 452 строк данных.  На реальном складе может быть 12 тысяч ячеек, а не как в демонстрационной 10-20 штук.
  • Далее начинается "веселье". Еще одно соединение с временной таблицей СкладыИПомещения, это требуется для определения адресности по складу в зависимости от даты начала использования. И в этом случае у нас получается почти 10 миллиардов строк. Выделено на картинке под индексом 2.
    (!) Внимательный читатель посмотрит на запрос выше и скажет: "Откуда появляются 10 миллиардов строк. Происходит внутреннее соединение по условию Склад и Помещение. У ячейки владелец - это Склад, а реквизит Помещение. Должна быть одна запись на запрос, т.е. остаться 10 миллионов строк.". Ответ на этот вопрос можно получить, если посмотреть как получается временная таблица СкладыИПомещения.
    В запросе ее создания мы видим, что соединяется таблица складов с помещениями. А затем с таблицей товаров, по условию склада. 
    Мысль понятна, оставить только входящие склады в таблицу товаров. Но вот из-за этого нелогичного соединения у нас появляется размножение. На мой взгляд, стоит поставить оператор "РАЗЛИЧНЫЕ" или использовать условие для фильтра склада с оператором "В". От таблицы товаров не выбирается не одного поля, а она используется в качестве отбора. (P.S. У меня походу работы накопилось достаточно много вопросов к автору сего шедевра)
  • И в конце концов у нас выполняется выборка различных. Как мы все знаем, то это обычно оператор группировки. См. индекс 3. В данном случае для таблицы 10 миллиардов записей не хватило места в оперативной памяти выделенного процессу (это около 1ГБ). И Postgress решил выполнять сортировку на жестком диске.

 

 

Есть ли проблемы в плане запроса? Может, планировщик ошибается? Как вы думаете?

На самом деле ответ - нет. Планировщик не ошибается, а делает то что мы от него просим. В данном случае происходит и должно происходить перемножение с помощью Nested Loop.

(!) Подобный подход с перемножением мне встречался ранее - при проверке остатков товаров организаций, там тоже получаются дикие промежуточные временные таблицы. В том случае происходит что-то подобное - умножение всех доступных видов запасов на таблицу остатков товаров организаций. 

Давайте разбираться дальше. Вспомним название временной таблицы - ТоварыВЯчейкахОтбор. Это данные для фильтра. Теперь посмотрим где она используется. А используется она только в одном запросе пакета - при получении временной таблицы ТоварыВЯчейках:

 
 Позиция использования временной таблицы ТоварыВЯчейкахОтбор

 

	////////////////////////////////////////////////////////////////////////////////
	ВЫБРАТЬ
		Остатки.Назначение КАК Назначение,
		Остатки.Номенклатура КАК Номенклатура,
		Остатки.Характеристика КАК Характеристика,
		Остатки.Ячейка КАК Ячейка,
		Остатки.Упаковка КАК Упаковка,
		Остатки.Серия КАК Серия,
		Остатки.ВНаличииОстаток - Остатки.КОтборуОстаток КАК ВНаличии
	ПОМЕСТИТЬ ТоварыВЯчейках
	ИЗ
		РегистрНакопления.ТоварыВЯчейках.Остатки(,
				(Назначение, Номенклатура, Характеристика, Ячейка) В(
					ВЫБРАТЬ
						Фильтр.Назначение КАК Назначение,
						Фильтр.Номенклатура КАК Номенклатура,
						Фильтр.Характеристика КАК Характеристика,
						Фильтр.Ячейка КАК Ячейка
					ИЗ
						ТоварыВЯчейкахОтбор КАК Фильтр)) КАК Остатки
	
	ОБЪЕДИНИТЬ ВСЕ
	
	ВЫБРАТЬ
		Движения.Назначение КАК Назначение,
		Движения.Номенклатура КАК Номенклатура,
		Движения.Характеристика КАК Характеристика,
		Движения.Ячейка КАК Ячейка,
		Движения.Упаковка КАК Упаковка,
		Движения.Серия КАК Серия,
		ВЫБОР
			КОГДА Движения.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
				ТОГДА -Движения.ВНаличии
			ИНАЧЕ Движения.ВНаличии
		КОНЕЦ КАК ВНаличии
	ИЗ
		РегистрНакопления.ТоварыВЯчейках КАК Движения
			ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТоварыВЯчейкахОтбор КАК Фильтр
			ПО Фильтр.Назначение = Движения.Назначение
				И Фильтр.Номенклатура = Движения.Номенклатура
				И Фильтр.Характеристика = Движения.Характеристика
				И Фильтр.Ячейка = Движения.Ячейка
	ГДЕ
		Движения.Регистратор = &Регистратор
			И Движения.Активность
	ИНДЕКСИРОВАТЬ ПО
		Ячейка
	;
	////////////////////////////////////////////////////////////////////////////////

 

В итоге, на мой взгляд, - это попытка многогранной оптимизации. Одна из целей - учесть все поля индекса для максимального быстродействия.  Пояснения ниже:

(!) Как мы прекрасно знаем, то при использовании виртуальной таблицы остатков регистра накопления создается таблица итогов на конец каждого месяца + таблица итогов оперативных остатков. В нашем случае используется таблица оперативных остатков, т.к. период не задан.

Для  этой таблицы итогов создается набор индексов (на рис. ниже последняя таблица). Один из них - кластерный и содержит в себе набор измерений по порядку их расположения в структуре реквизитов группы измерения регистра. 

 

 

Однако, как мы видим, то разработчики явно пропустили одно измерение - упаковку. Добавим все возможные варианты упаковок и сделаем еще один цикл? Итого у нас получится 100 миллиардов записей и это полный мрак, зато все поля индекса используются максимально.

Что будем делать? Смотрим ниже.

 

III) Пути решения.

 

Прежде чем начинать придумывать как исправить эту проблемную ситуацию давайте вспомним что в предыдущей версии все работало достаточно быстро. Открываем старую версию и смотрим тот же модуль и подобную функцию.

В старой версии есть такая же функция и похожий пакет запроса:

 
 Код функции ТаблицаПомещенияЯчейкиПоТоварам ERP 2.4

 

Если сравнить эти две функции для различных конфигураций, то мы увидим, что они достаточно похожи. Изменения заключаются в оптимизации:

  • Избавление от вложенных запросов. Часть вынесли в отдельные временные таблицы и обозвали как таблицы отборы. Другую часть представили как таблицы остатков по разделам;
  • Добавили отборы внутрь виртуальных таблиц;
  • Добавили индексы.

Посмотрим как выглядит вариант получения остатков товаров в ячейках - целевая часть применения временной таблицы отборов в ячейках:

 
 Предыдущая итерация кода

 

	////////////////////////////////////////////////////////////////////////////////
	ВЫБРАТЬ
		Таблица.Назначение,
		Таблица.Номенклатура,
		Таблица.Характеристика,
		Таблица.Серия,
		Таблица.Склад,
		Таблица.Помещение,
		Таблица.Упаковка,
		Таблица.Ячейка,
		СУММА(Таблица.ВНаличии) КАК ВНаличии,
		МАКСИМУМ(Таблица.СвободныйОстаток) КАК СвободныйОстаток,
		МАКСИМУМ(Таблица.Количество) КАК Количество
	ПОМЕСТИТЬ ТоварыВЯчейкахОстатки
	ИЗ
		(ВЫБРАТЬ
			ТоварыВЯчейкахОстатки.Назначение КАК Назначение,
			ТоварыВЯчейкахОстатки.Номенклатура КАК Номенклатура,
			ТоварыВЯчейкахОстатки.Характеристика КАК Характеристика,
			ТоварыВЯчейкахОстатки.Серия КАК Серия,
			ТоварыВЯчейкахОстатки.Ячейка.Владелец КАК Склад,
			ТоварыВЯчейкахОстатки.Ячейка.Помещение КАК Помещение,
			ТоварыВЯчейкахОстатки.Упаковка КАК Упаковка,
			ТоварыВЯчейкахОстатки.Ячейка КАК Ячейка,
			ТоварыВЯчейкахОстатки.ВНаличииОстаток - ТоварыВЯчейкахОстатки.КОтборуОстаток КАК ВНаличии,
			Т.СвободныйОстаток КАК СвободныйОстаток,
			Т.Количество КАК Количество
		ИЗ
			РегистрНакопления.ТоварыВЯчейках.Остатки КАК ТоварыВЯчейкахОстатки
				ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВтТоварыЗаказа КАК Т
				ПО ТоварыВЯчейкахОстатки.Назначение = Т.Назначение
					И ТоварыВЯчейкахОстатки.Номенклатура = Т.Номенклатура
					И ТоварыВЯчейкахОстатки.Характеристика = Т.Характеристика
					И ТоварыВЯчейкахОстатки.Ячейка.Владелец = Т.Склад
		
		ОБЪЕДИНИТЬ ВСЕ
		
		ВЫБРАТЬ
			ТоварыВЯчейках.Назначение,
			ТоварыВЯчейках.Номенклатура,
			ТоварыВЯчейках.Характеристика,
			ТоварыВЯчейках.Серия,
			ТоварыВЯчейках.Ячейка.Владелец,
			ТоварыВЯчейках.Ячейка.Помещение,
			ТоварыВЯчейках.Упаковка,
			ТоварыВЯчейках.Ячейка,
			ВЫБОР
				КОГДА ТоварыВЯчейках.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
					ТОГДА -ТоварыВЯчейках.ВНаличии
				ИНАЧЕ ТоварыВЯчейках.ВНаличии
			КОНЕЦ,
			Т.СвободныйОстаток,
			Т.Количество
		ИЗ
			РегистрНакопления.ТоварыВЯчейках КАК ТоварыВЯчейках
				ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВтТоварыЗаказа КАК Т
				ПО ТоварыВЯчейках.Назначение = Т.Назначение
					И ТоварыВЯчейках.Номенклатура = Т.Номенклатура
					И ТоварыВЯчейках.Характеристика = Т.Характеристика
					И ТоварыВЯчейках.Ячейка.Владелец = Т.Склад
		ГДЕ
			ТоварыВЯчейках.Регистратор = &Регистратор) КАК Таблица
	
	СГРУППИРОВАТЬ ПО
		Таблица.Назначение,
		Таблица.Номенклатура,
		Таблица.Характеристика,
		Таблица.Серия,
		Таблица.Склад,
		Таблица.Помещение,
		Таблица.Упаковка,
		Таблица.Ячейка
	;	////////////////////////////////////////////////////////////////////////////////

 

 

Делаем выводы по изменениям в версии ERP 2.5:

  • Вложенный запрос был вынесен во временную таблицу - ТоварыВЯчейках;
  • Соединение фильтр также было вынесено во временную таблицу - ТоварыВЯчейкахОтбор;
  • Дополнительно добавлять в таблицу отборов ячейку не имеет практической ценности.  

Фактически таблицу отборов в ячейках можно смело выкинуть из запроса и вместо нее брать временную таблицу заказов, а сам код получится чуть проще (учитываем, что таблица товаров должна быть свернута в рамках назначения, номенклатуры, характеристики, склада). Смотрим ниже:

 
 Изменение запроса получения остатков товаров в ячейках

 

	////////////////////////////////////////////////////////////////////////////////
	ВЫБРАТЬ
		Остатки.Назначение КАК Назначение,
		Остатки.Номенклатура КАК Номенклатура,
		Остатки.Характеристика КАК Характеристика,
		Остатки.Ячейка КАК Ячейка,
		Остатки.Упаковка КАК Упаковка,
		Остатки.Серия КАК Серия,
		Остатки.ВНаличииОстаток - Остатки.КОтборуОстаток КАК ВНаличии
	ПОМЕСТИТЬ ТоварыВЯчейках
	ИЗ
		РегистрНакопления.ТоварыВЯчейках.Остатки(,
	//			(Назначение, Номенклатура, Характеристика, Ячейка) В(
	//				ВЫБРАТЬ
	//					Фильтр.Назначение КАК Назначение,
	//					Фильтр.Номенклатура КАК Номенклатура,
	//					Фильтр.Характеристика КАК Характеристика,
	//					Фильтр.Ячейка КАК Ячейка
	//				ИЗ
	//					ТоварыВЯчейкахОтбор КАК Фильтр)) КАК Остатки
				(Назначение, Номенклатура, Характеристика, Ячейка.Владелец) В(
					ВЫБРАТЬ
						Фильтр.Назначение КАК Назначение,
						Фильтр.Номенклатура КАК Номенклатура,
						Фильтр.Характеристика КАК Характеристика,
						Фильтр.Склад КАК Склад
					ИЗ
						ВтТоварыЗаказа КАК Фильтр)) КАК Остатки
	
	ОБЪЕДИНИТЬ ВСЕ
	
	ВЫБРАТЬ
		Движения.Назначение КАК Назначение,
		Движения.Номенклатура КАК Номенклатура,
		Движения.Характеристика КАК Характеристика,
		Движения.Ячейка КАК Ячейка,
		Движения.Упаковка КАК Упаковка,
		Движения.Серия КАК Серия,
		ВЫБОР
			КОГДА Движения.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
				ТОГДА -Движения.ВНаличии
			ИНАЧЕ Движения.ВНаличии
		КОНЕЦ КАК ВНаличии
	ИЗ
		РегистрНакопления.ТоварыВЯчейках КАК Движения
	//		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТоварыВЯчейкахОтбор КАК Фильтр
	//		ПО Фильтр.Назначение = Движения.Назначение
	//			И Фильтр.Номенклатура = Движения.Номенклатура
	//			И Фильтр.Характеристика = Движения.Характеристика
	//			И Фильтр.Ячейка = Движения.Ячейка
			ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВтТоварыЗаказа КАК Фильтр
			ПО Фильтр.Назначение = Движения.Назначение
				И Фильтр.Номенклатура = Движения.Номенклатура
				И Фильтр.Характеристика = Движения.Характеристика
				И Фильтр.Склад = Движения.Ячейка.Владелец
	ГДЕ
		Движения.Регистратор = &Регистратор
			И Движения.Активность
	ИНДЕКСИРОВАТЬ ПО
		Ячейка
	;
	////////////////////////////////////////////////////////////////////////////////

 

 

Краткий итог:

После доработки пакетного запроса проблема "зависания" ушла, исчезла и более нас не беспокоила. И мы перешли к другим проблемным частям в коде конфигурации. А их было много, что-то вылавливаем до сих пор. 

Таким образом мы с вами исключили сложный и фактически излишний кусок запроса, который самым отрицательным образом влияет на производительность "живых"/"настоящих" рабочих баз. 

(!) Коллеги у меня накопилось еще с десяток интересных примеров по результатам апгрейда конфигурации ERP заказчика, если Вам интересно - пишите, и я постараюсь опубликовать их в ближайшее время.

См. также

HighLoad оптимизация Программист Платформа 1С v8.3 Бесплатно (free)

Метод очень медленно работает, когда параметр приемник содержит намного меньше свойств, чем источник.

06.06.2024    9260    Evg-Lylyk    61    

44

HighLoad оптимизация Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Анализ простого плана запроса. Оптимизация нагрузки на ЦП сервера СУБД используя типовые индексы.

13.03.2024    5097    spyke    28    

49

HighLoad оптимизация Программист Платформа 1С v8.3 Бесплатно (free)

Оказывается, в типовых конфигурациях 1С есть, что улучшить!

13.03.2024    7573    vasilev2015    20    

42

HighLoad оптимизация Инструменты администратора БД Системный администратор Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Обработка для простого и удобного анализа настроек, нагрузки и проблем с SQL сервером с упором на использование оного для 1С. Анализ текущих запросов на sql, ожиданий, конвертация запроса в 1С и рекомендации, где может тормозить.

2 стартмани

15.02.2024    12422    241    ZAOSTG    80    

115

HighLoad оптимизация Системный администратор Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Принимать, хранить и анализировать показания счетчиков (метрики) в базе 1С? Почему бы нет? Но это решение быстро привело к проблемам с производительностью при попытках построить какую-то более-менее сложную аналитику. Переход на PostgresSQL только временно решил проблему, т.к. количество записей уже исчислялось десятками миллионов и что-то сложное вычислить на таких объемах за разумное время становилось все сложнее. Кое-что уже практически невозможно. А что будет с производительностью через пару лет - представить страшно. Надо что-то предпринимать! В этой статье поделюсь своим первым опытом применения СУБД Clickhouse от Яндекс. Как работает, что может, как на нее планирую (если планирую) переходить, сравнение скорости работы, оценка производительности через пару лет, пример работы из 1С. Все это приправлено текстами запросов, кодом, алгоритмами выполненных действий и преподнесено вам для ознакомления в этой статье.

1 стартмани

24.01.2024    5669    glassman    18    

40

HighLoad оптимизация Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Встал вопрос: как быстро удалить строки из ТЗ? Рассмотрел пять вариантов реализации этой задачи. Сравнил их друг с другом на разных объёмах данных с разным процентом удаляемых строк. Также сравнил с выгрузкой с отбором по структуре.

09.01.2024    14017    doom2good    49    

71
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. kser87 2470 29.05.23 13:08 Сейчас в теме
В общем-то проблему с перемножением строк можно было обнаружить простой консолью запросов, которая количество записей во временных таблицах умеет показывать.
EvgeniyOlxovskiy; Alien_RS_Forever; корум; Punisher_1C; Кадош; krot_poliglot; muskul; Andreeei; bocharovki; olexi2012; cheshirshik; Jimbo; +12 Ответить
3. ivanov660 4577 29.05.23 14:44 Сейчас в теме
(1)
1. Мы рассказываем про подход к поиску и анализу проблем - у него есть плюсы и минусы.
2. Зачем, нам использовать консоль запросов, когда данные для анализа уже готовы - бери и смотри.
3. Мы используем консоль запросов в том случае, когда не понятна сама проблема и требуется проводить эксперименты.
EvgeniyOlxovskiy; sulfur17; bugagashenka; +3 Ответить
5. kser87 2470 30.05.23 12:08 Сейчас в теме
(3) идея публикации понятна. Читается как готовая инструкция. Просто предложил простой способ поиска решения проблем.
EvgeniyOlxovskiy; +1 Ответить
8. ivanov660 4577 30.05.23 13:04 Сейчас в теме
(5) Для массового поиска проблем, использовать консоль не удобно. Для рассмотрения конкретной задачи, можно.
EvgeniyOlxovskiy; +1 Ответить
2. booksfill 29.05.23 13:16 Сейчас в теме
Не понял почему вы сочли неверную попытку оптимизации - "чрезмерной оптимизацией"?
Это все равно, что сказать: "решили пилить бревно не ножовкой, а бензопилой, но забыли ее завести - поэтому все стало в 1000 раз хуже".

По-моему, ЧРЕЗМЕРНАЯ оптимизация плоха тем, что может приводить к снижению соотношения затраченные_усилия/полученный_результат, а также к серьезным потерям при попытках дальнейшей модернизации полученного решения.
Но и вариант - одно улучшили, другое ухудшили - не ваш случай, ибо улучшение читаемости кода или соответствий рекомендациям ИТС, дающее в итоге не рабочее решение, нельзя рассматривать как решение в принципе.
EvgeniyOlxovskiy; Pine-river; Alien_RS_Forever; Stylo; zqzq; Andreeei; bocharovki; Evg-Lylyk; bulpi; olexi2012; Sashares; SP2000; cheshirshik; +13 Ответить
9. ivanov660 4577 30.05.23 13:55 Сейчас в теме
(2) Чрезмерный - превосходящий необходимую достаточную меру. Под достаточной мерой я считаю вариант реализации показанный в конце статьи. Да, он не идеально оптимизированный, но отрабатывает за приемлемое время. Стремиться учесть все возможные требования как делали разработчики, на мой взгляд, не целесообразно.
То что разработчики допустили некоторые ошибки при проектировании запросов - это отдельная ситуация.
4. VSvintsov1 30.05.23 05:11 Сейчас в теме
в тексте скромненько так ....Postgres ... Если писать статью , то для сравнения этот же код желательно и на MS SQL прогнать. Огромная вероятность что проблем бы не было. И тогда обсуждение "оптимизации" перешло бы в другую плоскость:
может быть обратно на MS SQL?
:-)
P.S.
знаю знаю: импортозамещение, официальный сайт единого реестра российских программ, Postgres бесплатно.
но ведь подавляющему количеству бизнесов это не критично
7. ivanov660 4577 30.05.23 13:02 Сейчас в теме
(4)Проблемы также будут, если внимательно посмотреть запрос.
user865160; +1 Ответить
6. Sodrugestvo 30.05.23 12:16 Сейчас в теме
Отличный разбор, особо здорово - что все методично
sulfur17; ivanov660; +2 Ответить
10. artbear 1563 30.05.23 15:52 Сейчас в теме
(0) Ух ты, я не знал, что можно указать вложенное поле (Ячейка.Владелец) в условие
(Х1, Х2, ...) В (запрос)


(Назначение, Номенклатура, Характеристика, Ячейка.Владелец) В(
fatman78; triviumfan; +2 Ответить
11. ivanov660 4577 31.05.23 09:40 Сейчас в теме
(10) Для составных типов такой "финт" лучше не делать или проверить несколько раз. Для текущего примера - минус одна временная таблица (мы учитываем, что складов в системе обычно не так много).
12. triviumfan 97 05.06.23 11:31 Сейчас в теме
Заметил, что измерение "Ячейка" индексировано. Получается, имеется ещё и некластерный индекс.
СУБД не может использовать 2 индекса одновременно?
Оставьте свое сообщение