Пост

ВыполнитьЗапросСАналитикой()

Иногда так нужно проанализировать время и результат сложного запроса прямо в отладке!


Предлагаю свою версию решения этой задачки 👌 Несложная функция, которая клонирует переданный запрос и выполняет его пакеты с получением результата и замером времени. Учитывает все переданные параметры и временные таблицы в МВТ.

И при этом не задевает переданный запрос! И он выполнится так же, словно вы ничего не совершали. Удобно, когда в запросе есть менеджер временных таблиц, который “сломает” повторное выполнение.

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Замеряет скорость выполнения запроса и получает его выгрузки
// Возвращает результат анализа запроса и полученные данные. При этом переданный объект запроса не выполняется
// Удобно использовать в отладке для анализа запроса прямо с установленными параметрами и МВТ
// Функция будет поддерживаться и обновляться на FastCode: https://fastcode.im/Templates/7426
//
// 1. Выбирает все данные из менеджера временных таблиц
// 2. Создает копию запроса с новым менеджером таблиц
// 3. Выполняет копию запроса в разрезе пакетов
// 4. Замеряет скорость выполнения каждого пакета
// 5. Выбирает данные результатов выполнения
// 6. Возвращает результат анализа запроса
//
// Параметры:
//  ВходящийЗапрос  - Запрос - Анализируемый запрос
//
// Возвращаемое значение:
//   Таблица значений   - результат анализа
//
Функция ВыполнитьЗапросСАналитикой(ВходящийЗапрос) Экспорт
	
	ДанныеПакетов = Новый ТаблицаЗначений;
	
	ДанныеПакетов.Колонки.Добавить("НомерСтроки" , Новый ОписаниеТипов("Число"));
	ДанныеПакетов.Колонки.Добавить("Тип"         , Новый ОписаниеТипов("Строка"));
	ДанныеПакетов.Колонки.Добавить("ИмяТаблицы"  , Новый ОписаниеТипов("Строка"));
	ДанныеПакетов.Колонки.Добавить("Миллисекунды", Новый ОписаниеТипов("Число"));
	ДанныеПакетов.Колонки.Добавить("Записей"     , Новый ОписаниеТипов("Число"));
	ДанныеПакетов.Колонки.Добавить("ЕстьДанные"  , Новый ОписаниеТипов("Булево"));
	ДанныеПакетов.Колонки.Добавить("Данные"      , Новый ОписаниеТипов("ТаблицаЗначений"));
	
	ДанныеПакетов.Индексы.Добавить("ИмяТаблицы");
	
	Запрос = Новый Запрос;
	Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
	
	Если ВходящийЗапрос.МенеджерВременныхТаблиц <> Неопределено Тогда
		
		Для Каждого ВременнаяТаблица Из ВходящийЗапрос.МенеджерВременныхТаблиц.Таблицы Цикл
			
			ВыбираемыеПоля = Новый Массив;
			Для Каждого ОписаниеКолонки Из ВременнаяТаблица.Колонки Цикл
				ВыбираемыеПоля.Добавить(ОписаниеКолонки.Имя);
			КонецЦикла;
			
			Запрос.Текст = СтрШаблон("ВЫБРАТЬ %1 ПОМЕСТИТЬ %2 ИЗ &ВременнаяТаблица КАК ВТ", 
			СтрСоединить(ВыбираемыеПоля, ","), ВременнаяТаблица.ПолноеИмя);
			
			ДанныеВременнойТаблицы = ВременнаяТаблица.ПолучитьДанные().Выгрузить();
			Запрос.УстановитьПараметр("ВременнаяТаблица", ДанныеВременнойТаблицы);
			
			Запрос.Выполнить();
			
			ОписаниеПакета = ДанныеПакетов.Добавить();
			ОписаниеПакета.ИмяТаблицы  = ВременнаяТаблица.ПолноеИмя;
			ОписаниеПакета.Данные      = ДанныеВременнойТаблицы;
			ОписаниеПакета.ЕстьДанные  = Истина;
			ОписаниеПакета.Тип = "Таблица менеджера";
			
			Запрос.Текст = "";
			Запрос.Параметры.Удалить("ВременнаяТаблица");
			
		КонецЦикла;
		
	КонецЕсли;
	
	Для Каждого КлючИЗначение Из ВходящийЗапрос.Параметры Цикл
		Запрос.УстановитьПараметр(КлючИЗначение.Ключ, КлючИЗначение.Значение);
	КонецЦикла;
	
	СхемаЗапроса = Новый СхемаЗапроса;
	СхемаЗапроса.УстановитьТекстЗапроса(ВходящийЗапрос.Текст);
	Для Каждого ПакетЗапроса Из СхемаЗапроса.ПакетЗапросов Цикл
		
		ОписаниеПакета = ДанныеПакетов.Добавить();
		
		Если ТипЗнч(ПакетЗапроса) = Тип("ЗапросУничтоженияТаблицыСхемыЗапроса") Тогда
			
			Запрос.Текст = "УНИЧТОЖИТЬ " + ПакетЗапроса.ИмяТаблицы;
			ОписаниеПакета.ЕстьДанные  = Ложь;
			ОписаниеПакета.ИмяТаблицы = Запрос.Текст;
			ОписаниеПакета.Тип = "Уничтожение";
			
		Иначе
			
			ОписаниеПакета.ЕстьДанные  = Истина;
			Если ПустаяСтрока(ПакетЗапроса.ТаблицаДляПомещения) Тогда
				ОписаниеПакета.Тип = "Выборка";
			Иначе
				ОписаниеПакета.Тип = "Помещение";
				СуществующийПакет  = ДанныеПакетов.Найти(ПакетЗапроса.ТаблицаДляПомещения, "ИмяТаблицы");
				Если СуществующийПакет <> Неопределено Тогда
					Запрос.Текст = "УНИЧТОЖИТЬ " + ПакетЗапроса.ТаблицаДляПомещения;
					Запрос.Выполнить();
					ДанныеПакетов.Удалить(СуществующийПакет);
				КонецЕсли;
			КонецЕсли;
			
			ОписаниеПакета.ИмяТаблицы = ПакетЗапроса.ТаблицаДляПомещения;
			
			Запрос.Текст = ПакетЗапроса.ПолучитьТекстЗапроса();
			
		КонецЕсли;
		
		НачалоЗамера    = ТекущаяУниверсальнаяДатаВМиллисекундах();
		РезультатЗапрос = Запрос.Выполнить();
		КонецЗамера     = ТекущаяУниверсальнаяДатаВМиллисекундах();
		
		ОписаниеПакета.Данные       = ДанныеВременнойТаблицы;
		ОписаниеПакета.Миллисекунды = КонецЗамера-НачалоЗамера;
		
		Если ОписаниеПакета.ЕстьДанные Тогда
			Если ОписаниеПакета.Тип = "Выборка" Тогда
				ДанныеПакета = РезультатЗапрос.Выгрузить();
			Иначе
				ДанныеПакета = Запрос.МенеджерВременныхТаблиц.Таблицы.Найти(ОписаниеПакета.ИмяТаблицы).ПолучитьДанные().Выгрузить();
			КонецЕсли;
			ОписаниеПакета.Данные = ДанныеПакета;
		КонецЕсли;
		
	КонецЦикла;
	
	Для НомерСтроки = 1 По ДанныеПакетов.Количество() Цикл
		ОписаниеПакета = ДанныеПакетов[НомерСтроки-1];
		ОписаниеПакета.НомерСтроки = НомерСтроки;
		Если ОписаниеПакета.ЕстьДанные Тогда
			ОписаниеПакета.Записей = ОписаниеПакета.Данные.Количество();
			Если ОписаниеПакета.Записей = 0 Тогда
				ОписаниеПакета.ЕстьДанные = Ложь;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
	Возврат ДанныеПакетов;
	
КонецФункции
Авторский пост защищен лицензией CC BY 4.0 .