Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Как получить параллельной план  [new]
acava
Member

Откуда: Москва
Сообщений: 8
Здравствуйте. Прошу прощения если тема уже обсуждалось, сходу не нашёл. Подскажите в какую сторону смотреть или может какие ссылки по теме есть.
Два запрос, использующие конструкцию cross apply с одной и той же inline функцией с рекурсивным запросом, имеют разные планы выполнения. Хочется получить для второго запроса параллельный план такой же, как и для первого.
--Запрос1
SELECT t2.*
FROM dbo.PointParams t1
CROSS APPLY dbo.GetPPRelations1 (t1.ID_PP) t2

--Запрос2
SELECT t2.*
FROM dbo.tt1 t1
CROSS APPLY dbo.GetPPRelations1 (t1.ID_PP) 


CREATE FUNCTION dbo.GetPPRelations1 (@ID_PP int)
RETURNS TABLE 
AS
RETURN
WITH C0 AS
(
SELECT @ID_PP AS ID_PP_Upper
	  ,CAST(0 AS int) AS NUM
	  ,CAST('19000101' AS datetime) AS DT1
	  ,CAST('22000101' AS datetime) AS DT2
UNION ALL
SELECT t1.ID_PP
	  ,CAST(1 AS int) AS NUM
	  ,(CASE WHEN t1.DT1 > t2.DT1 THEN t1.DT1 ELSE t2.DT1 END) AS DT1
	  ,(CASE WHEN t1.DT2 < t2.DT2 THEN t1.DT2 ELSE t2.DT2 END) AS DT2
	FROM dbo.SchemaRealation t1
	JOIN C0 t2 ON t1.ID_Ref = t2.ID_PP_Upper AND t1.DT1 < t2.DT2 AND t1.DT2 > t2.DT1
)
,CTE AS
(
SELECT ID_PP_Upper, DT1, MAX(DT2) AS DT2
	FROM C0 WHERE NUM = 1
GROUP BY ID_PP_Upper, DT1
)
SELECT ID_PP_Upper, MIN(DT1) AS DT1, DT2
	FROM CTE
GROUP BY ID_PP_Upper, DT2
GO

--Содержит 13 617 записей
CREATE TABLE dbo.tt1 (ID_PP int  NOT NULL PRIMARY KEY)

--Содержит 406 774 записей
CREATE TABLE dbo.PointParams (ID_PP int NOT NULL IDENTITY PRIMARY KEY)

--Содержит 386 058 записей
CREATE TABLE dbo.SchemaRealation
(
 ID_PP int NOT NULL
,ID_Ref int NOT NULL
,DT1 datetime NOT NULL
,DT2 datetime NULL
PRIMARY KEY CLUSTERED (ID_PP, ID_Ref, DT1)
)
GO

CREATE UNIQUE NONCLUSTERED INDEX IX_SchemaRealation ON dbo.SchemaRealation (ID_Ref, ID_PP, DT1) INCLUDE (DT2)
GO


+
Планы
https://yadi.sk/d/YoW6EPpBwCSsu



PS: если имеет значения
select @@version

Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64)
Jun 17 2016 19:14:09
Copyright (c) Microsoft Corporation
Developer Edition: (64-bit) on Windows NT 6.3 <X64> (Build 9600: )

К сообщению приложен файл. Размер - 124Kb
4 окт 16, 15:04    [19742411]     Ответить | Цитировать Сообщить модератору
 Re: Как получить параллельной план  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
Ну, всегда есть трейс-флаг QUERYTRACEON 8649.
4 окт 16, 15:42    [19742618]     Ответить | Цитировать Сообщить модератору
 Re: Как получить параллельной план  [new]
o-o
Guest
он же не дурной параллелить 13 617 записей.
дешевле не параллелить.
флагом заставить можно, но еще проще записей подлить, чтобы стало тоже 406 774
4 окт 16, 16:45    [19742967]     Ответить | Цитировать Сообщить модератору
 Re: Как получить параллельной план  [new]
acava
Member

Откуда: Москва
Сообщений: 8
Спасибо за помощь.
4 окт 16, 16:58    [19743057]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Как получить параллельной план  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 867
Гавриленко Сергей Алексеевич
Ну, всегда есть трейс-флаг QUERYTRACEON 8649.
Что-то ни трейс-флаг ни хинт мне не помогли.

Пробовал разные варианты типа
option (use hint('ENABLE_PARALLEL_PLAN_PREFERENCE'))
option (querytraceon 8649)
option (recompile, querytraceon 8649)
Применение не выдает никаких ошибок но и не влияет на параллельность.

Если вкратце необходимо выполнить очень прожорливую к CPU обработку строк. Тест кейс
if object_id('tempdb..#tmp') is not null drop table #tmp

;with r1000(i) as (select 0 union all select r1000.i + 1 from r1000 where r1000.i < 1000-1)
select t1.i + t2.i * 1000 id
  into #tmp
 from r1000 t1, r1000 t2
option (maxrecursion 0)

select *
from #tmp t
where replicate('w',100)+'str'+replicate('w',100)+cast(id as varchar) like '%str%666666%'


Выполняется в параллели если сбросить порог в ноль
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
GO
EXEC sp_configure 'cost threshold for parallelism', 0;
RECONFIGURE;
GO
EXEC sp_configure 'show advanced options', 0;
RECONFIGURE;


Либо если применить изысканный трюк
SELECT       
    x.*        
FROM dbo.make_parallel() AS mp        
CROSS APPLY        
(        
  select *
  from #tmp t
  where replicate('w',100)+'str'+replicate('w',100)+cast(id as varchar) like '%str%666666%'
) AS x


Есть ли какие-то еще способы повлиять на стоимость или игнорировать порог?
Конечная цель - добиться параллельного выполнения без создания объектов и без вызова sp_configure.

PS. Microsoft SQL Server 2017
20 ноя 20, 04:12    [22235830]     Ответить | Цитировать Сообщить модератору
 Re: Как получить параллельной план  [new]
invm
Member

Откуда: Москва
Сообщений: 9827
Кобанчег,

У запроса уровень оптимизации TRIVIAL. Поэтому и не праллелится.
Вот так попробуйте
select *
from #tmp t
where replicate('w',100)+'str'+replicate('w',100)+cast(id as varchar) like (select '%str%666666%')
20 ноя 20, 09:42    [22235877]     Ответить | Цитировать Сообщить модератору
 Re: Как получить параллельной план  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 867
invm,

Спасибо. А ларчик просто открывался.

Интересно что план считается trivial даже для секционированной (и не временной таблицы) и не параллелится.
А ведь подобные запросы могут быть заметно ускорены параллельностью с минимальным overhead на её организацию.
22 ноя 20, 16:12    [22236578]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить