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

Откуда:
Сообщений: 10
Подскажите пожалуйста почему такой план получается в первом запросе.

Таблица:
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Links](
	[Source] [int] NOT NULL,
	[Destination] [int] NOT NULL,
	[Date] [datetime] NULL DEFAULT (getdate()),
	[TypeID] [smallint] NOT NULL,
 CONSTRAINT [PK_Links] PRIMARY KEY CLUSTERED 
(
	[Source] ASC,
	[TypeID] ASC,
	[Destination] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

CREATE NONCLUSTERED INDEX [IX_Links_Destination] ON [dbo].[Links]
(
	[Destination] ASC,
	[TypeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO


Тестовые данные:
INSERT INTO [dbo].[Links]([Source], [Destination], [Date], [TypeID])
SELECT o.[object_id], o2.[object_id], GETDATE(), 1 FROM sys.[objects] o
CROSS JOIN sys.[objects] o2 


Запрос:
IF OBJECT_ID('tempdb..#Inserted') IS NOT NULL DROP TABLE #Inserted
CREATE TABLE #Inserted 
(
  [ID] Int NOT NULL PRIMARY KEY CLUSTERED
) 

INSERT INTO #Inserted([ID])
SELECT TOP (10) o.[object_id] FROM sys.[objects] o 


SELECT DISTINCT
  [ID] = CASE WHEN I.[ID] = TL.[Source] THEN TL.[Destination] ELSE TL.[Source] END
FROM [dbo].[Links] TL
INNER JOIN #Inserted I ON I.[ID] = TL.[Source]
  OR I.[ID] = TL.[Destination]


SELECT DISTINCT
  TL.[Destination]
FROM [dbo].[Links] TL
INNER JOIN #Inserted I ON I.[ID] = TL.[Source]
UNION
SELECT DISTINCT
  TL.[Source]
FROM [dbo].[Links] TL
INNER JOIN #Inserted I ON I.[ID] = TL.[Destination]


В первом случае (с OR в соединении) Index Scan.
Во втором (с UNION) Index Seek. Почему?

К сообщению приложен файл (1.sqlplan - 46Kb) cкачать
24 апр 18, 13:25    [21364197]     Ответить | Цитировать Сообщить модератору
 Re: Почему такой план (Index Scan)  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 36694
Потому что не умеет сервер разворачивать OR в два сика с объединением. И, вроде, не научили еще (но это не точно).
24 апр 18, 13:29    [21364233]     Ответить | Цитировать Сообщить модератору
 Re: Почему такой план (Index Scan)  [new]
nullin
Member

Откуда: pullin
Сообщений: 140
newLoginSql, Зачем Вам вообще OR?
SELECT DISTINCT
       [ID] = CASE WHEN I.[ID] = TL.[Source] THEN TL.[Destination] ELSE TL.[Source] END
  FROM [dbo].[Links] TL
 CROSS APPLY (SELECT [V] = 1 UNION ALL SELECT [V] = 0) X
 INNER JOIN #Inserted I 
    ON I.[ID] = TL.[Destination]
25 апр 18, 02:21    [21366382]     Ответить | Цитировать Сообщить модератору
 Re: Почему такой план (Index Scan)  [new]
nullin
Member

Откуда: pullin
Сообщений: 140
nullin, вместо cross apply, еще можно заставить seek by fake left join (on 1=1) того же набора из двух значений.
25 апр 18, 02:28    [21366386]     Ответить | Цитировать Сообщить модератору
 Re: Почему такой план (Index Scan)  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6794
nullin
newLoginSql, Зачем Вам вообще OR?
SELECT DISTINCT
       [ID] = CASE WHEN I.[ID] = TL.[Source] THEN TL.[Destination] ELSE TL.[Source] END
  FROM [dbo].[Links] TL
 CROSS APPLY (SELECT [V] = 1 UNION ALL SELECT [V] = 0) X
 INNER JOIN #Inserted I 
    ON I.[ID] = TL.[Destination]

агонь! можно сократить до SELECT 1 какая разница
25 апр 18, 08:47    [21366620]     Ответить | Цитировать Сообщить модератору
 Re: Почему такой план (Index Scan)  [new]
nullin
Member

Откуда: pullin
Сообщений: 140
TaPaK, А что Вам там не нравится?
sqlfiddle
25 апр 18, 09:50    [21366766]     Ответить | Цитировать Сообщить модератору
 Re: Почему такой план (Index Scan)  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6794
nullin
TaPaK, А что Вам там не нравится?
sqlfiddle

ну если упёртый, то расскажи
когда же I.[ID] = TL.[Source] случится в вашей агонии?
25 апр 18, 09:51    [21366769]     Ответить | Цитировать Сообщить модератору
 Re: Почему такой план (Index Scan)  [new]
nullin
Member

Откуда: pullin
Сообщений: 140
TaPaK, да, Вы правы, хотел обойти OR, но что-то пошло не так.

WITH TLC as
(SELECT TL.[Source], TL.[Destination], X.[V],
        [CROSS] = CASE WHEN X.[V] = 1 THEN TL.[Destination] ELSE TL.[Source] END
   FROM [dbo].[Links] TL
  CROSS APPLY (SELECT [V] = 1 UNION ALL SELECT [V] = 0) X) 
 
 SELECT DISTINCT
        [ID] = CASE WHEN TLC.[V] = 1 THEN TLC.[Source] 
                    WHEN TLC.[V] = 0 THEN TLC.[Destination] 
               END
   FROM TLC
  INNER JOIN #Inserted I 
     ON I.[ID] = TLC.[CROSS];

Seek не запустился.
25 апр 18, 11:23    [21367127]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить