Имя: Пароль:
1C
1С v8
Секционирование регистра накопления
, , ,
0 VitShvets
 
28.05.18
15:04
А баловался ли кто-нибудь? Есть регистр накопления, остатки. Секционировал по «_Period» таблицу итогов, по годам. Когда пишу 1Совый запрос:

РегистрНакопления.МойРегистр.Остатки(, [Отбор по одному полю в 50 тысяч строк])
1С это превращает в:

exec sp_executesql('.....
....
FROM dbo._AccumRgT27531 T2 WITH(NOLOCK)
WHERE T2._Period = P1
.....' P1 datetime2(3).... '5999-11-01 00:00:00'

В итоге SQL, из за sp_executesql и не явного указания периодов, не понимает что надо поднимать только одну секцию с периодом '5999-11-01 00:00:00' и поднимает все секции. Хотя если в менеджмент студии переписать запрос на:

FROM dbo._AccumRgT27531 T2 WITH(NOLOCK)
WHERE T2._Period = '5999-11-01 00:00:00'
….

Всё работает! Разница в скорости колоссальная – 1 секунда против 3 минут.

Решение есть - отказаться от запросов 1С против прямых запросов, но уж больно не хочется этого делать. Есть идеи как можно повлиять на
РегистрНакопления.МойРегистр.Остатки ?
96 VitShvets
 
20.06.18
16:05
(90) Я правильно идею понимаю? Делаем регистр оборотным, вешаем агрегаты, добавляем регламентное заполнение регистра сведений как "итогов". В целевом запросе по остаткам собираем "итоги" + обороты за нужный период. Есть где почитать? Но, имхо, проще тогда уж прямые запросы. Не нужно новые сущности плодить, а запрос по сути тот-же самый - "ближние итоги плюс обороты". А в SQL и индекс можно подобрать и вообще...
(91) >> Кто бы мог подумать!
Вот не надо тут. Я не сомневался, что пересчет итогов поможет, но ожидал сокращения записей не более чем на несколько десятков процентов. То, что количество записей сократились в разы, и приятное и не приятное открытие. Приятное, что помогло быстро решить локальную задачу. Неприятное, что этим надо следить и следить пристально.  Через месяц буду анализировать скорость деградации, видимо писать job'ы/регламенты.
(92), (93) Я что-то пропустил? Агрегаты вроде как можно только для оборотного регистра создать? Я использовал, оборотный регистр "Продажи". Отчёты, если в агрегат попадёшь, строятся очень быстро.
97 Fragster
 
гуру
20.06.18
16:09
кстати, может быть проще выключить итоги по периодам и оставить только текущие итоги?
98 VitShvets
 
20.06.18
16:22
(94) Татычё?! Есть такая штука в составе средств управления сиквелом, профайлер называется. Он позволяет, в том числе "ловить" запросы генерируемые непосредственно 1С, вместе с актуальными их планами. Естественно запрос можно взять и нежно "покрутить" уже в SSMS, посмотреть как меняется его план.
(95) А поведай ка мне Антон Долгов, какие-нибудь есть идеи на тему 2-х терабайтной базы на предмет "обрезать", "ускорить" и всего-вот-этого-вот? При условии что монопольного доступа к базе есть 1-2 часа в сутки и сильно не каждый день. Или только овна на вентилятор вбросить не слабо? Не знаю с какого перепуга какой-то там Рупасов кого-то там расстреливал, это всяко не говорит о его выдающихся умственных способностях, во всяком случае в твоём изложении.
99 Genayo
 
20.06.18
16:42
(96) Таки да, для оборотных агрегаты. Мы об этом и говорим :)
100 Genayo
 
20.06.18
16:45
(97) Тогда надо делать 2 базы - одну оперативную, только с текущими итогами, а другую отчетную - наоборот без текущих итогов. Ибо если в базе только с текущими итогами задать период хотябы год - помрет нафик с такими объемами, как у ТС...
101 VitShvets
 
20.06.18
16:55
(97) Не, иногда требуется посмотреть сильно прошлый период. Я попробую поиграться урезанием "старых периодов", что 8.3 умеет сама установкой минимального периода итогов. Профайлером посмотрю запросы-зависимости, попробую руками почистить. Но для начала надо понять скорость деградации таблицы итогов, особенно оперативных.
102 VitShvets
 
20.06.18
17:10
(99) Так агрегаты ещё с 8.2, если не 8.1 появились. В 8.3 добавили им интеллекта по поводу "рекомендаций" и позволили управлять из предприятия.
(100) Я думал про 2 базы - архивная и оперативная. В оперативной последние 3-6 месяцев, в архивной всё остальное. Народ работает только в оперативной, длинная отчетность формируется в архивной. Не придумал как их создать быстро и как связывать между собой на предмет актуализации архивной. Так чтобы это работало быстро.
103 Антон Долгов
 
20.06.18
17:39
(98) Что именно тебе надо ускорить?
104 Genayo
 
20.06.18
17:43
(102) Объемы в сутки очень большие? РИБ не прокатит?
105 romix
 
20.06.18
18:00
(0) Смотрели стандартную обработку Все действия - стандартные обработки - управление итогами - полные возможности?


Полные возможности

Режим полных возможностей позволяет получить полный доступ ко всем инструментам работы с итогами (закладка Итоги) и агрегатами (закладка Агрегаты) регистров накопления и регистров бухгалтерии.
106 VitShvets
 
20.06.18
18:07
(103) Ну как обычно - проведение документов, всякие регламентные операции.  Самое тяжелое, типовые 1Совые запросы, на которые я не могу никак повлиять. Это виртуальные таблицы "срез последних" и "остатки".
(104) Очень приличные. На пределе. Если будет какой-то сбой, уже есть шанс не догнать. Особенно в контексте планов роста. РИБ по функционалу меня устраивает полностью. Скорее всего будет гибрид какой-то. Метаданные и лёгкие объекты метаданных ходят РИБом, тяжелые SQL.
107 Антон Долгов
 
20.06.18
18:11
(106) И какой у тебя самый медленный запрос и какой у него план? Выложи в формате sqlplan
108 romix
 
20.06.18
18:20
http://1sprogress.ru/anatomiya-registra-nakopleniya-vnutrennee-ustrojstvo-i-struktura-xraneniya.html

1С хранит текущие актуальные остатки (если поставить галку в настройках!) и хранит помесячно от сих до сих (две даты можно поставить в той же форме настроек (105).

Таблицы можно пересчитать.

То есть вот это надо посмотреть. Далее надо думать что там лучше по сути - регистр остатков или оборотов, закрывается ли он в 0, или там все время растет таблица остатков со временем.
109 VitShvets
 
20.06.18
18:21
(107) В (0) написано. Не самый, но один из. План не выложу, но там смотреть нечего. Не интересный - более 50% кластеред индекс сик таблицы итогов в части оперативных итогов. Остальное впополам иннер джоин с времянкой-отбором и "агрегация" хэш матчем. Основное в плане, что кластеред индекс сик партиционирован, количество актуальных секций =14.
110 romix
 
20.06.18
18:22
Пересчет таблицы итогов еще нужен ибо http://catalog.mista.ru/public/177171/
111 Антон Долгов
 
20.06.18
18:24
(109) без партиционирования запрос какой тормозит и какой у него план? что побудило заняться партиционированием? может надо с этого начинать?
112 H A D G E H O G s
 
20.06.18
18:27
(109) Там остаточных предикатов точно нет?
113 Антон Долгов
 
20.06.18
18:30
(112) а додумывай сам! хрен тебе а не sqlplan, "там смотреть нечего"
114 H A D G E H O G s
 
20.06.18
18:35
Хотяяя.
Я правильно понимаю, что автор вытаскивает ВСЕ оперативные итоги, которых 50 тыс строк?
115 mistеr
 
20.06.18
18:35
(102) Про схему архивная-оперативная и быструю актуализацию можно забыть. Пока 1С не разрешит использовать возможности скуля по быстрой обработке больших объемов данных средствами 1С. То есть многострочный DML.
116 VitShvets
 
20.06.18
18:48
(105), (108) Эта история работает с режима совместимости 8.3.5. У меня 8.2.
(110) Это видел, подчерпнул оттуда пару идей.
(111) А разве не очевидно, что побудило? Скорость работы не устраивает. Причём основные тормоза именно в тех местах на, которые я повлиять не могу. Обычные "ВЫБРАТЬ бла-бла из ххх.Остатки". Или "ххх.СрезПоследних".
(113) Нельзя выкладывать. СБ и всё такое.
117 VitShvets
 
20.06.18
18:55
(112) Вот сейчас не уверен, что точно понял о чём ты. Поясни плз, что ты имеешь ввиду, на что посмотреть?
(114) Не все, 50 тысяч из нескольких миллионов. Есть кластерный индекс, в нем первое поле период, второе поле, то что участвует в отборе.
118 VitShvets
 
20.06.18
18:57
(115) Да я как-то не шибко жажду спрашивать разрешения у 1С... Но мне больше нравится CDC.
119 H A D G E H O G s
 
20.06.18
18:58
(117) Отбой тревоги. Остаточный предикат работает только в диапазоне индекса. К твоей проблеме это не может относиться.
120 H A D G E H O G s
 
20.06.18
18:58
Сейчас я попытаюсь воспроизвести твои идеи.
121 nicxxx
 
20.06.18
19:00
(43) в кластерный может попадать из-за того, что много полей тянутся из таблицы.
Important: SQL Server does not use nonclustered indexes if it estimates that a large number of key or RID lookup operations will be required. (Korotkevitch D. - Pro SQL Server Internals)
122 mistеr
 
20.06.18
19:00
(118) Не спрашивать разрешения это значит жить без поддержки и в постоянном страхе, что завтра с очередным обновлением платформы все поломается.

Есть еще вариант сделать хранилище в отдельной базе (не 1С), сделать его грамотно и юзать как внешний источник.
123 H A D G E H O G s
 
20.06.18
19:05
Но вообще, цифры ты приводишь дикие.

Я грешу на непрогретый кэш.
Но даже после DROPCLEANBUFFERS у меня цифры минимальны.
Без всяких секционирований.
124 H A D G E H O G s
 
20.06.18
19:10
SELECT count(*)
      
FROM [IEGAIS_MP].[dbo].[_AccumRgT687]

Результат: 8896130 за 49 секунд


SELECT *      
  FROM [IEGAIS_MP].[dbo].[_AccumRgT687]
  where [_Period]= ('59991101 00:00:00.000') and _Fld679RRef=0x810E000D3A22309E11E5EC30EF6782BC

После перезапуска ms sql сервер
Результат: 50598 строк за 0,6 секунд
HDD WD 5400, 2 Тб
Подозреваю, что жив кэш HDD
125 H A D G E H O G s
 
20.06.18
19:11
0,6 секунд вполне укладывается в твою 1 секунду. Но без секционирования.
Что то не так у тебя с запросом от 1С.
126 H A D G E H O G s
 
20.06.18
19:11
Сейчас сделаю запрос через 1С.
127 H A D G E H O G s
 
20.06.18
19:21
Ну как бэ через 1С то совсем другой запрос получается, автор.
С вложенной таблицей и группировочкой разделенных итогов.
128 H A D G E H O G s
 
20.06.18
19:38
В любом случае, после перезапуска 1С и MS SQL запрос
    Запрос=Новый Запрос;
    Старт=ТекущаяУниверсальнаяДатаВМиллисекундах();
    Запрос.Текст=
    "ВЫБРАТЬ
    |    ТоварыНаСкладахОстатки.Организация,
    |    ТоварыНаСкладахОстатки.ОбособленноеПодразделение,
    |    ТоварыНаСкладахОстатки.Склад,
    |    ТоварыНаСкладахОстатки.Номенклатура,
    |    ТоварыНаСкладахОстатки.Серия,
    |    ТоварыНаСкладахОстатки.КоличествоОстаток
    |ИЗ
    |    РегистрНакопления.ТоварыНаСкладах.Остатки(, Организация = &Организация) КАК ТоварыНаСкладахОстатки";
    Запрос.УстановитьПараметр("Организация",Объект.Организация);
    Выборка=Запрос.Выполнить().Выбрать();
    Стоп=ТекущаяУниверсальнаяДатаВМиллисекундах();
    Сообщить(Строка(Выборка.Количество())+" строк за "+Строка(Стоп-Старт)+" мсек.");

Выполняется:
42 074 строк за 3 002 мсек.

Размер таблицы 8896130 строк

В профайлере он же
exec sp_executesql N'SELECT
T1.Fld679RRef,
T1.Fld680RRef,
T1.Fld681RRef,
T1.Fld682RRef,
T1.Fld683RRef,
T1.Fld684Balance_
FROM (SELECT
T2._Fld679RRef AS Fld679RRef,
T2._Fld680RRef AS Fld680RRef,
T2._Fld681RRef AS Fld681RRef,
T2._Fld682RRef AS Fld682RRef,
T2._Fld683RRef AS Fld683RRef,
CAST(SUM(T2._Fld684) AS NUMERIC(22, 2)) AS Fld684Balance_
FROM dbo._AccumRgT687 T2
WHERE T2._Period = P1 AND ((T2._Fld679RRef = @P2)) AND (T2._Fld684 <> @P3) AND (T2._Fld684 <> @P4)
GROUP BY T2._Fld679RRef,
T2._Fld680RRef,
T2._Fld681RRef,
T2._Fld682RRef,
T2._Fld683RRef
HAVING (CAST(SUM(T2._Fld684) AS NUMERIC(22, 2))) <> 0.0) T1',N'P1 datetime2(3),@P2 varbinary(16),@P3 numeric(10),@P4 numeric(10)','5999-11-01 00:00:00',0x811F000D3A223D1B11E6056572D76893,0,0
129 H A D G E H O G s
 
20.06.18
19:40
Проблема, скорее всего как раз в секциях. Он видит секции и начинает в них шарить, несмотря на индекс.
130 vs84
 
20.06.18
20:15
(0) а если в отборе не 50 тыс, а 1 тыс - план аналогичный?
131 VitShvets
 
20.06.18
20:23
(122) Это решается вьюхами. 1С спокойно себе работает с таблицами и не знает про вьюхи. Перенос данных спокойно себе работает со вьюхами и не знает про таблицы. Даже если 1С что-то поменяет в структуре хранения, актуализируем вьюхи, продолжаем работать.
(129) Сиквел хитро работает с секциями, они указаны в дереве индексов. В моём случае, т.к. он трогает все секции, я не получаю выигрыша от секционирования, "трогается" вся таблица, но по первому полю в индексе отбираются строки где Period = '5999-11-01'.
132 H A D G E H O G s
 
20.06.18
20:28
Почему трогаются все секции?
133 VitShvets
 
20.06.18
20:30
(130) На сколько я понял по тестам, ключевое отличие тут равенство или другое условие. Если взять пример (128), и предположить, что организация есть второе поле кластерного индекса после периода, то запрос:
РегистрНакопления.ТоварыНаСкладах.Остатки(, Организация = &Организация)

Полностью покроется кластерным индексом. Без дополнительных inner join. У меня же условие выглядит как:

РегистрНакопления.МойРегистр.Остатки(, ЗаказПокупателя В (ВЫБРАТЬ ВТ1.ЗаказПокупателя ИЗ ВТ1))

Где ВТ1 таблица в одно поле, 50 тысяч записей, только ссылки на заказы. И тут уже план другой получается. Поднимается по кластерному записи только по периоду, а потом иннер-джоинятся уже с ВТ1.
134 VitShvets
 
20.06.18
20:32
(132) :) Я собственно ради решения этого вопроса и тему создал. Причём берешь 1Совый запрос, меняешь совсем чуть-чуть, получаешь даже не тех-же самых данных кардинально иной результат.
135 H A D G E H O G s
 
20.06.18
21:07
(133) Вот мы и стали ближе к истине на 1 шаг.

Есть же теперь понимание того, что
РегистрНакопления.МойРегистр.Остатки(, ЗаказПокупателя В (ВЫБРАТЬ ВТ1.ЗаказПокупателя ИЗ ВТ1))

использует индекс только по Периоду, без участия в нем ЗаказПокупателя

?
136 H A D G E H O G s
 
20.06.18
21:49
Хех.
Сделал секционирование, как у автора и нарвался на его проблему.
137 H A D G E H O G s
 
20.06.18
21:49
Щас Дима разберется.
138 H A D G E H O G s
 
20.06.18
22:02
Как только в запросе начинают использоваться параметры - секционирование не работает
139 H A D G E H O G s
 
20.06.18
22:04
Секционирование работает:

exec sp_executesql N'SELECT
T1.Fld671RRef,
T1.Fld672RRef,
T1.Fld673RRef,
T1.Fld674RRef,
T1.Fld675RRef,
T1.Fld863_,
T1.Fld676Balance_
FROM (SELECT
T2._Fld673RRef AS Fld673RRef,
T2._Fld675RRef AS Fld675RRef,
T2._Fld671RRef AS Fld671RRef,
T2._Fld672RRef AS Fld672RRef,
T2._Fld674RRef AS Fld674RRef,
T2._Fld863 AS Fld863_,
CAST(SUM(T2._Fld676) AS NUMERIC(27, 3)) AS Fld676Balance_
FROM dbo._AccumRgT677 T2
WHERE T2._Period = ''59991101 00:00:00.000'' AND ((T2._Fld671RRef = 0x810E000D3A22309E11E5EC30EF6782BC)) AND (T2._Fld676 <> 0) AND (T2._Fld676 <> 0)
GROUP BY T2._Fld673RRef,
T2._Fld675RRef,
T2._Fld671RRef,
T2._Fld672RRef,
T2._Fld674RRef,
T2._Fld863
HAVING (CAST(SUM(T2._Fld676) AS NUMERIC(27, 3))) <> 0.0) T1',N'@P1 datetime2(3),@P2 varbinary(16),@P3 numeric(10),@P4 numeric(10)','5999-11-01 00:00:00',0x811F000D3A223D1B11E6056572D76893,0,0
140 H A D G E H O G s
 
20.06.18
22:05
Секционирование не работает:

exec sp_executesql N'SELECT
T1.Fld671RRef,
T1.Fld672RRef,
T1.Fld673RRef,
T1.Fld674RRef,
T1.Fld675RRef,
T1.Fld863_,
T1.Fld676Balance_
FROM (SELECT
T2._Fld673RRef AS Fld673RRef,
T2._Fld675RRef AS Fld675RRef,
T2._Fld671RRef AS Fld671RRef,
T2._Fld672RRef AS Fld672RRef,
T2._Fld674RRef AS Fld674RRef,
T2._Fld863 AS Fld863_,
CAST(SUM(T2._Fld676) AS NUMERIC(27, 3)) AS Fld676Balance_
FROM dbo._AccumRgT677 T2
WHERE T2._Period = P1 AND ((T2._Fld671RRef = @P2)) AND (T2._Fld676 <> @P3) AND (T2._Fld676 <> @P4)
GROUP BY T2._Fld673RRef,
T2._Fld675RRef,
T2._Fld671RRef,
T2._Fld672RRef,
T2._Fld674RRef,
T2._Fld863
HAVING (CAST(SUM(T2._Fld676) AS NUMERIC(27, 3))) <> 0.0) T1',N'P1 datetime2(3),@P2 varbinary(16),@P3 numeric(10),@P4 numeric(10)','5999-11-01 00:00:00',0x811F000D3A223D1B11E6056572D76893,0,0
141 H A D G E H O G s
 
20.06.18
22:07
Я бы на месте автора сходил бы на sql.ru, там бы сразу ответили, думаю.
142 H A D G E H O G s
 
20.06.18
22:07
С примерами из 139 -140
143 Genayo
 
20.06.18
22:12
(140)Интересно, что было бы на постгресе...
144 H A D G E H O G s
 
20.06.18
22:13
В 139 префикс поиска ptnid1000=1
В 140 префикс поиска ptnid1000>=1 и ptnid1000<=3
145 H A D G E H O G s
 
20.06.18
22:13
Собственно, у меня 3 секции
146 H A D G E H O G s
 
20.06.18
22:14
147 H A D G E H O G s
 
20.06.18
22:15
148 H A D G E H O G s
 
20.06.18
22:22
Немного не то, у товарища в условии - функция.
149 H A D G E H O G s
 
20.06.18
22:34
151 Антон Долгов
 
20.06.18
23:12
(149) т.е. ты слился?
152 H A D G E H O G s
 
20.06.18
23:16
(151) system, ты не выеживайся, расскажи лучше нам, почему ты до этого сам не дошел.
153 H A D G E H O G s
 
20.06.18
23:17
(151) Ну и статью почитай, про динамическую фильтрацию.
154 Антон Долгов
 
20.06.18
23:17
Вот интересно, какой-то чувак из Волгограда чота прочитал где-то про что-то и решил это у себя попробовать. Ок, ему простительно, он из региона и всё такое. Но ты-то Ежов, ты же сертифицированный иксперд, как ты повелся на невнятное блеяние и начал потакать хотелкам нуба?
155 H A D G E H O G s
 
модератор
20.06.18
23:18
Давай, до свидания.
158 breezee
 
21.06.18
03:06
(5) Ага, на ура...
Выбрать в () будет работать очень медленно.
Если нужно обрезать данные, то лучше использовать внутреннее соединение
159 nicxxx
 
21.06.18
08:53
(158) Дело не в том, как ты напишешь код запроса, а в том, какой оптимизатор построит план. Он может построить одинаковый план для inner join и in ().
160 ERWINS
 
21.06.18
09:51
РегистрНакопления.МойРегистр.Остатки(, ЗаказПокупателя В (ВЫБРАТЬ ВТ1.ЗаказПокупателя ИЗ ВТ1))

в часто приводит к скану. Лучше
РегистрНакопления.МойРегистр.Остатки(, ЗаказПокупателя = &знаение)   если одно значение, тогда вроде он ВСЕГДА использует индекс сик

Кроме того попробуйте сделать для ВТ1 индекс по заказу, тогда возможен индекс мердж
161 toypaul
 
гуру
21.06.18
10:00
"Недокументировано" лезешь в базу и хочешь чтобы 1С тебя поняла? Будь готов к тому что не поймет и "отказаться от запросов 1С"

"Есть идеи как можно повлиять на РегистрНакопления.МойРегистр.Остатки ?" есть. написать в 1С, чтобы они учли это в новых релизах
162 toypaul
 
гуру
21.06.18
10:01
exec sp_executesql('.....
....
FROM dbo._AccumRgT27531 T2 WITH(NOLOCK)
WHERE T2._Period = P1
.....' P1 datetime2(3).... '5999-11-01 00:00:00'

я правильно понимаю что 1С генерит несколько таких запросов вместо одного? пуская и с sp_executesql. или запрос один и все портит sp_executesql?
163 VitShvets
 
21.06.18
12:21
Уххх, какая ожесточенная схватка :) А Антон Долгов, это такой местный сумасшедший? Обижаться нельзя, ибо на таких обижаться непрактично?

(139), (140) Именно так. А круче всего результат получается, если во времянку-условие добавить ещё константное поле Период со значением '5999-11-01 00:00:00' и сделать inner join по заказу+периоду с таблицей итогов. На моих данных, сейчас 0.5 секунды против 12 без секций и 6-7 секунд с секцями.
164 VitShvets
 
21.06.18
12:25
(144) схожу, правда мне кажется, что там сходу посоветуют как надо запрос переписать, чтобы секции сработали. А я это и так уже знаю. Мне бы 1С заставить каким-то хитрым способом объяснить сиквелу... Но схожу. Коли будет результат, сюда отпишусь.
165 VitShvets
 
21.06.18
12:30
(158), (159) Inner join хорошо срабатывает когда соединяется с физической таблицей. Виртуальная таблица, это "select ... from (select ..." и join будет с внешним select... Т.е. отбора по заказам, в моём случае, не будет на уровне выборки из таблицы итогов.
166 VitShvets
 
21.06.18
12:33
(160) Понятно, что "ЗаказПокупателя = &знаение" будет лучше, но мне то надо по списку заказов.
Я индексирую ВТ, но у меня на времянке индекс скан получается.
167 H A D G E H O G s
 
21.06.18
12:35
(166) Ты же понимаешь, что ты делаешь фигню?
168 VitShvets
 
21.06.18
12:36
(161) Я вот как раз и сопротивляюсь до последнего "недокументированному лазанью" в базу. Хочется минимальными затратами получить максимальный профит. Как обычно впрочем.
169 VitShvets
 
21.06.18
12:40
(162) 1С генерирует один запрос. Всё портит "sp_executesql", а точнее то, что оптимизатор при построении плана не учитывает значение параметров. Не уверен что это именно оно, но очень похоже на "Parameter sniffing".
170 VitShvets
 
21.06.18
12:41
(167) Ты про индексирование? Я не увидел разницу с индексами и без. По крайней мере по запросам, что рождает 1С. Это тесты всё.
171 VitShvets
 
21.06.18
12:43
(167) Есть кстати жгучее желание испить немного пенных напитков и обсудить ряд жизненноважных проблем :)
172 Genayo
 
21.06.18
13:03
(170) На 50000 записей и не увидишь...
173 H A D G E H O G s
 
21.06.18
13:05
(170) Именно.
Если ВТ велика (больше 1000 строк, конкретное значение уж не помню) - SQL не использует индекс при соединении.
Ведь, чтобы использовать индекс - нужен nested loops - проход по строкам временной таблицы и для каждой строки временной таблицы - индексный поиск в виртуальной.
Если строк ВТ будет много - SQL может посчитать, что проще обойти обе таблицы через mergejoin.
174 H A D G E H O G s
 
21.06.18
13:07
mergejoin будет еще более вероятен, если ВТ и Виртуальная таблицы индекскированы. Но не из-за индекса, а из-за того, что таблицы УПОРЯДОЧЕНЫ по полю поиска из за наличия этого индекса.

Но, упорядочить ВТ можно, не создавая Индекс, а отсортировав, что более дешево. Индекс опять не нужен, НО.
175 H A D G E H O G s
 
21.06.18
13:07
В вашем примере mergejoin использован не будет
176 H A D G E H O G s
 
21.06.18
13:10
Ибо, чтобы использовать mergejoin, нужно 2 таблицы, которых у вас пока нет, пока не выполниться поиск по Периоду из таблицы остатков.

По идее, если задать хинт на использование mergejoin, то SQL выполнит TableSpool (сохранение промежуточной таблицы в tempDB, фактически, та же временная таблица, средствами SQL) для результата отбора по периоду для таблицы остатков, дико медленную и потом сделает mergejoin с вашей временной.
177 H A D G E H O G s
 
21.06.18
13:10
Поэтому, SQL сделает HashJoin
178 H A D G E H O G s
 
21.06.18
13:12
SQL построит хэштаблицу для вашей временной таблицы, затем выберет записи из таблицы остатков по периоду и обойдет эти записи, ища их строки в хэштаблице.
179 los_hooliganos
 
21.06.18
13:15
(169) Все верно. Построитель запроса не знает параметров, поэтому строит план запроса на все секции.
180 los_hooliganos
 
21.06.18
13:20
Я бы сделал вьюху с таким вот условием:

WHERE case T2._Period = '2001-01-01 00:00:00' and '2002-01-01 00:00:00' and $PARTITION.partition_function(_Period) = 2001 then true

Секционирование заработает и особо извращаться не надо и построитель запроса все должен учесть.
181 los_hooliganos
 
21.06.18
13:21
(180) ну ес-но в CASE сам пропиши соотношения периодов и секций
182 los_hooliganos
 
21.06.18
13:23
точнее :)

WHERE case when view.Period between '2001-01-01 00:00:00' and '2002-01-01 00:00:00' and $PARTITION.partition_function(Period) = 2001 then true
when ... then

end
183 VitShvets
 
21.06.18
13:30
(177), (178) У меня mergejoin получается во всех вариантах.
184 H A D G E H O G s
 
21.06.18
13:48
(183) значит я что-то не учел.
185 Fragster
 
гуру
21.06.18
14:27
получается автору надо поместить остатки в ВТ, а потом её уже отбирать.
186 H A D G E H O G s
 
21.06.18
14:50
(183) Воспроизвел твою ситуацию - HashMatch
187 H A D G E H O G s
 
21.06.18
14:54
Однако я ошибся с 1000 строк ВТ.

У меня ВТ была на 30Кстрок (при 8млн. строк таблицы остатков) - был nested_loops. 30 тыс поисков по индексу в таблице остатков.
Увеличил ВТ до 80Кстрок - стал hash_join.
Видимо, есть какое то отношение размера внешней и внутренней таблицы.
188 VitShvets
 
21.06.18
16:54
(185) Выигрыша не будет. Это тоже самое, что получить все оперативные остатки.
189 VitShvets
 
21.06.18
16:55
(186) У меня есть TRC, где в одном случае нестед лупс есть, но взял сейчас тот запрос, не получатся повторить, везде mergejoin...
190 VitShvets
 
21.06.18
16:56
(187) Вот тоже такое ощущение. Сейчас записей меньше стало, планы поменялись.
192 Fragster
 
гуру
21.06.18
17:07
(188) ну так веь ты говоришь, что у тебя все секции дергаются. а это не только оперативные остатки, но и помесячные итоги, которых в несколько (десятков) раз больше
193 VitShvets
 
21.06.18
17:13
(191) Ты зря перестал принимать такие кругленькие штучки, что тётя доктор прописала. Береги себя.
194 VitShvets
 
21.06.18
17:21
(192) Дёргаются, да, но по дереву индексов всёравно я получаю оперативные итоги, что на следующем шаге иннер джоянятся mergejoin-ом с времянкой-фильтром. Как итог, с сервера вытягиваются данные только по 50 тысячам заказов. Если делать внутреннее соединение с виртуальной таблицей или складывать остатки во времянку, а потом соединять две времянки, будет как минимум дольше на вытягивание всех итогов и/или создание временной таблицы.
195 МихаилМ
 
25.06.18
23:26