1C Query Optimization Skill (Advanced Patterns)
This skill provides advanced query patterns beyond basic rules in 1c-rules.md.
For basic query rules (formatting, aliases, parameters, no queries in loops) — see 1c-rules.md.
When to Use
Invoke this skill when:
- •Working with complex multi-step data processing
- •Optimizing joins and subqueries
- •Implementing DCS reports
- •Processing large datasets in portions
Temporary Tables
Use temporary tables for:
- •Complex multi-step data processing
- •Joining data from multiple sources
- •Reusing intermediate results
Join vs Subquery
// ✅ PREFERRED: Join (usually faster) "ВЫБРАТЬ | Заказы.Ссылка КАК Заказ, | Контрагенты.ИНН КАК ИНН |ИЗ | Документ.ЗаказКлиента КАК Заказы | ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты | ПО Заказы.Контрагент = Контрагенты.Ссылка" // ⚠️ AVOID: Subquery in SELECT (N+1 problem) "ВЫБРАТЬ | Заказы.Ссылка КАК Заказ, | (ВЫБРАТЬ К.ИНН ИЗ Справочник.Контрагенты КАК К | ГДЕ К.Ссылка = Заказы.Контрагент) КАК ИНН |ИЗ | Документ.ЗаказКлиента КАК Заказы"
Avoid Aggregation in Subqueries
// ❌ SLOW: Subquery with aggregation "ВЫБРАТЬ | Номенклатура.Ссылка, | (ВЫБРАТЬ СУММА(Остатки.Количество) ...) КАК Остаток |ИЗ | Справочник.Номенклатура КАК Номенклатура" // ✅ FAST: Join with pre-aggregated data "ВЫБРАТЬ | Номенклатура.Ссылка КАК Номенклатура, | ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток |ИЗ | Справочник.Номенклатура КАК Номенклатура | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки | ПО Номенклатура.Ссылка = Остатки.Номенклатура"
Virtual Table Parameters
Use virtual table parameters instead of WHERE for better performance:
// ✅ CORRECT: Uses virtual table parameters (fast) "ВЫБРАТЬ | Остатки.Номенклатура КАК Номенклатура, | Остатки.КоличествоОстаток КАК Остаток |ИЗ | РегистрНакопления.ТоварыНаСкладах.Остатки( | &Дата, | Номенклатура В (&СписокНоменклатуры)) КАК Остатки" // ❌ WRONG: Virtual table then filter (slow) "ВЫБРАТЬ | Остатки.Номенклатура КАК Номенклатура, | Остатки.КоличествоОстаток КАК Остаток |ИЗ | РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата) КАК Остатки |ГДЕ | Остатки.Номенклатура В (&СписокНоменклатуры)"
DCS (Data Composition System) Optimization
Efficient DCS Queries
- •
Use parameters in query text:
bsl// Pass parameters to virtual table РегистрНакопления.Остатки.Остатки(&Период, Склад = &Склад)
- •
Limit data at source:
bsl// Add conditions in DataSet query, not in DCS settings ГДЕ Период >= &НачалоПериода
- •
Use ЕСТЬNULL for outer joins:
bslЕСТЬNULL(Остатки.Количество, 0) КАК Количество
Composite Type Dereferencing (ITS Standard)
Avoid dereferencing composite type reference fields directly — the system creates queries for ALL possible types.
// ❌ SLOW: Dereferences ALL registrar types (can be hundreds) "ВЫБРАТЬ | ТоварыНаСкладах.Регистратор.Дата КАК ДатаДокумента |ИЗ | РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах" // ✅ FAST: Use ВЫРАЗИТЬ to specify exact type "ВЫБРАТЬ | ВЫРАЗИТЬ(ТоварыНаСкладах.Регистратор КАК Документ.ПоступлениеТоваровУслуг).Дата КАК ДатаДокумента |ИЗ | РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах" // ✅ For multiple known types, use ВЫБОР/КОГДА "ВЫБРАТЬ | ВЫБОР | КОГДА ТоварыНаСкладах.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг | ТОГДА ВЫРАЗИТЬ(ТоварыНаСкладах.Регистратор КАК Документ.ПоступлениеТоваровУслуг).Дата | КОГДА ТоварыНаСкладах.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг | ТОГДА ВЫРАЗИТЬ(ТоварыНаСкладах.Регистратор КАК Документ.РеализацияТоваровУслуг).Дата | КОНЕЦ КАК ДатаДокумента |ИЗ | РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах"
Use ПРЕДСТАВЛЕНИЕ for Display (ITS Standard)
When you only need text representation, use ПРЕДСТАВЛЕНИЕ() to avoid extra joins:
// ❌ Creates additional subquery for Справочник.Склады "ВЫБРАТЬ | ТоварыНаСкладах.Склад.Наименование |ИЗ | РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах" // ✅ Optimal: No extra join "ВЫБРАТЬ | ПРЕДСТАВЛЕНИЕ(ТоварыНаСкладах.Склад) КАК СкладПредставление |ИЗ | РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах"
Avoid Joins with Subqueries (ITS Standard)
Never use subqueries in JOIN — use temporary tables instead:
// ❌ WRONG: Join with subquery "ВЫБРАТЬ ... |ИЗ | Документ.Заказ КАК Заказы | ЛЕВОЕ СОЕДИНЕНИЕ ( | ВЫБРАТЬ Товары.Заказ, СУММА(Товары.Сумма) КАК Сумма | ИЗ Документ.Заказ.Товары КАК Товары | СГРУППИРОВАТЬ ПО Товары.Заказ | ) КАК ИтогиТоваров | ПО Заказы.Ссылка = ИтогиТоваров.Заказ" // ✅ CORRECT: Use temporary table "ВЫБРАТЬ | Товары.Ссылка КАК Заказ, | СУММА(Товары.Сумма) КАК Сумма |ПОМЕСТИТЬ ИтогиТоваров |ИЗ | Документ.Заказ.Товары КАК Товары |СГРУППИРОВАТЬ ПО | Товары.Ссылка |ИНДЕКСИРОВАТЬ ПО | Заказ |; |ВЫБРАТЬ ... |ИЗ | Документ.Заказ КАК Заказы | ЛЕВОЕ СОЕДИНЕНИЕ ИтогиТоваров КАК ИтогиТоваров | ПО Заказы.Ссылка = ИтогиТоваров.Заказ"
Avoid Joins with Virtual Tables (ITS Standard)
Extract virtual table results to temporary table before joining:
// ⚠️ May be slow: Direct join with virtual table "ВЫБРАТЬ ... |ИЗ | Справочник.Номенклатура КАК Номенклатура | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата,) КАК Остатки | ПО Номенклатура.Ссылка = Остатки.Номенклатура" // ✅ BETTER: First extract to temporary table "ВЫБРАТЬ | Остатки.Номенклатура КАК Номенклатура, | Остатки.КоличествоОстаток КАК Остаток |ПОМЕСТИТЬ ВТОстатки |ИЗ | РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата,) КАК Остатки |ИНДЕКСИРОВАТЬ ПО | Номенклатура |; |ВЫБРАТЬ ... |ИЗ | Справочник.Номенклатура КАК Номенклатура | ЛЕВОЕ СОЕДИНЕНИЕ ВТОстатки КАК Остатки | ПО Номенклатура.Ссылка = Остатки.Номенклатура"
Avoid OR in WHERE — Use ОБЪЕДИНИТЬ ВСЕ (ITS Standard)
OR in WHERE prevents index usage. Split into UNION queries:
// ❌ SLOW: OR prevents index usage "ВЫБРАТЬ | Товары.Ссылка |ИЗ | Справочник.Номенклатура КАК Товары |ГДЕ | Товары.Артикул = &Артикул | ИЛИ Товары.Код = &Код" // ✅ FAST: Two indexed queries with UNION "ВЫБРАТЬ | Товары.Ссылка |ИЗ | Справочник.Номенклатура КАК Товары |ГДЕ | Товары.Артикул = &Артикул | |ОБЪЕДИНИТЬ ВСЕ | |ВЫБРАТЬ | Товары.Ссылка |ИЗ | Справочник.Номенклатура КАК Товары |ГДЕ | Товары.Код = &Код"
ОБЪЕДИНИТЬ vs ОБЪЕДИНИТЬ ВСЕ (ITS Standard)
Prefer ОБЪЕДИНИТЬ ВСЕ when no duplicate rows expected:
// ⚠️ SLOWER: ОБЪЕДИНИТЬ performs additional grouping "ВЫБРАТЬ ... ИЗ Документ.Приход |ОБЪЕДИНИТЬ |ВЫБРАТЬ ... ИЗ Документ.Расход" // ✅ FASTER: ОБЪЕДИНИТЬ ВСЕ skips grouping "ВЫБРАТЬ ... ИЗ Документ.Приход |ОБЪЕДИНИТЬ ВСЕ |ВЫБРАТЬ ... ИЗ Документ.Расход"
Index Alignment (ITS Standard)
Ensure query conditions match available indexes:
Index requirements:
- •Index must contain all fields from the condition
- •Fields must be at the beginning of the index
- •Fields must be consecutive (no gaps)
// Given index: (Организация, Контрагент, Дата) // ✅ Index will be used — fields are at the beginning "ГДЕ Организация = &Орг И Контрагент = &Контр" // ❌ Index NOT used — skipped first field "ГДЕ Контрагент = &Контр И Дата = &Дата" // ⚠️ Partial use — gap in fields "ГДЕ Организация = &Орг И Дата = &Дата"
Creating additional indexes:
- •Set "Индексировать" = "Индексировать с доп. упорядочиванием" for frequently filtered attributes
- •Add
ИНДЕКСИРОВАТЬ ПОfor temporary tables used in joins
Reference: ITS Query Optimization Standards
Remember: Verify metadata attributes exist using get_metadata_details (EDT MCP Server) before writing queries.