MSSQL - переменные в WHERE
От: amalakhov  
Дата: 12.05.10 08:56
Оценка:
Имеем 2 запроса:

SELECT UTC_Time, SC2
FROM Frames JOIN Science_data ON Frames.id = Science_data.id 
WHERE UTC_time BETWEEN '2009-09-15 21:43:14' AND '2009-09-15 23:43:14' AND GoodToMap = 1

и
DECLARE @curTime datetime;
SET @curTime = '2009-09-15 21:43:14';

SELECT UTC_Time, SC2
FROM Frames JOIN Science_data ON Frames.id = Science_data.id 
WHERE UTC_time BETWEEN @curTime AND DATEADD(hour, 2, @curTime) AND GoodToMap = 1


1й выполняется, второй уходит в перманентную задумчивость. C чем может быть связано?
Сервер MSSQL 2000 (версия 8.0.0.2040 SP4).
Если аналогичный 2му запрос выполнить но не напрямую, а через linked server — тоже всё хорошо.

Спасибо, о all!
Re: MSSQL - переменные в WHERE
От: Sshur Россия http://shurygin-sergey.livejournal.com
Дата: 12.05.10 09:20
Оценка:
Здравствуйте, amalakhov, Вы писали:

A>1й выполняется, второй уходит в перманентную задумчивость. C чем может быть связано?

A>Сервер MSSQL 2000 (версия 8.0.0.2040 SP4).

А в Activity Monitor для того процесса что висит, что показывается? чего он ждет?
Надо это посмотреть, и еще есть предположение, что для второго запроса оптимизатор почему-то решает не использовать индекс по UTC_time и поэтому начинает делать full scan, что для очень большой таблицы может быть эквивалентно "перманентной задумчивости"
Шурыгин Сергей

"Не следует преумножать сущности сверх необходимости" (с) Оккам
Re[2]: MSSQL - переменные в WHERE
От: skorpk Россия  
Дата: 12.05.10 09:26
Оценка:
Здравствуйте, Sshur, Вы писали:

S>Здравствуйте, amalakhov, Вы писали:


A>>1й выполняется, второй уходит в перманентную задумчивость. C чем может быть связано?

A>>Сервер MSSQL 2000 (версия 8.0.0.2040 SP4).

S>А в Activity Monitor для того процесса что висит, что показывается? чего он ждет?

S>Надо это посмотреть, и еще есть предположение, что для второго запроса оптимизатор почему-то решает не использовать индекс по UTC_time и поэтому начинает делать full scan, что для очень большой таблицы может быть эквивалентно "перманентной задумчивости"
Надо посмотреть план выполнения и структуру таблицы хорошо бы увидеть.
Да и глянуть что делается в данный момент а Activity Monitor
Re: MSSQL - переменные в WHERE
От: FilosOFF Россия  
Дата: 12.05.10 09:31
Оценка: 3 (1)
Здравствуйте, amalakhov, Вы писали:

Для начала, следует смотреть планы выполнения. Скорее всего, в первом случае, используется индекс. Во втором случае, опираясь на статистику, сервер считает что простой скан даст результат много быстрее, потому как данные отсортированы и т.п.
Решение простое, указать принудительное использование индексов.
Еще проблема может заключаться в том, что опятьтаки опираясь на статистику сиквель может выбрать определенный тип соединения , к примеру MERGE, а данных оказалось много и потому все висит (памяти мало, диск слабый). Решается указанием типа соединения.
Но все это можно легко и быстро определить посмотрев на план выполнения. Так что ждем планов!
... << RSDN@Home 1.2.0 alpha 4 rev. 1231>>
Re[3]: MSSQL - переменные в WHERE
От: amalakhov  
Дата: 12.05.10 10:12
Оценка:
Здравствуйте, skorpk, Вы писали:
S>Надо посмотреть план выполнения и структуру таблицы хорошо бы увидеть.
S>Да и глянуть что делается в данный момент а Activity Monitor

Структуры:
CREATE TABLE [dbo].[Frames](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [UTC_time] [datetime] NOT NULL,
    [GoodToMap] [tinyint] NOT NULL CONSTRAINT [DF_Frames_GoodToMap]  DEFAULT (0),
 CONSTRAINT [PK_Frames] PRIMARY KEY CLUSTERED 
(
    [id] ASC
) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[Science_data](
    [id] [bigint] NOT NULL,
    [SC2] [binary](32) NOT NULL,
 CONSTRAINT [PK_Science_data] PRIMARY KEY CLUSTERED 
(
    [id] ASC
) ON [PRIMARY]
) ON [PRIMARY]

ALTER TABLE [dbo].[Science_data]  WITH NOCHECK ADD  CONSTRAINT [FK_Science_data_Frames] FOREIGN KEY([id])
REFERENCES [dbo].[Frames] ([id])
GO
ALTER TABLE [dbo].[Science_data] CHECK CONSTRAINT [FK_Science_data_Frames]


План выполнения — действительно сильно разные — но тут я немножко профан и не до конца могу понимать смысла нарисованного. Если подскажете, возможно ли заставить сервер выполнять 2й запрос так же как 1й, кажется это решит проблемы.


По поводу Activity Monitor — во время выполнения 2го запроса там очень много жизни, но опять же — не до конца понимаю, на что именно обращать внимание (какие столбцы имеет смысл сюда приводить). Наш процесс — 60й.


PS. Пока пост писал — 2й вариант запроса таки выполнился, заняло 8 минут (против 1 секунды)
Re[2]: MSSQL - переменные в WHERE
От: amalakhov  
Дата: 12.05.10 10:16
Оценка:
Здравствуйте, FilosOFF, Вы писали:
FOF>Но все это можно легко и быстро определить посмотрев на план выполнения. Так что ждем планов!

Приложил в соседней ветке
Автор: amalakhov
Дата: 12.05.10
.
Re[4]: MSSQL - переменные в WHERE
От: FilosOFF Россия  
Дата: 12.05.10 10:16
Оценка: 3 (1)
Здравствуйте, amalakhov, Вы писали:

Ну, как я Вам и написал, в первом случае сервер делает LOOP соединение, во втором HASH.

Попробуйте вот так:
DECLARE @curTime DATETIME;
SET @curTime = '2009-09-15 21:43:14';

SELECT UTC_Time,
       SC2
FROM   Frames
       INNER LOOP JOIN Science_data
            ON  Frames.id = Science_data.id
WHERE  UTC_time BETWEEN @curTime AND DATEADD(hour, 2, @curTime)
       AND GoodToMap = 1
... << RSDN@Home 1.2.0 alpha 4 rev. 1231>>
Re[4]: MSSQL - переменные в WHERE
От: FilosOFF Россия  
Дата: 12.05.10 10:20
Оценка:
Да, и еще, для того, чтобы было более понятно с поанами. Используйте дерективу SET SHOWPLAN_TEXT ON/OFF и приводите то, что выводится, в виде текста.
... << RSDN@Home 1.2.0 alpha 4 rev. 1231>>
Re[5]: MSSQL - переменные в WHERE
От: amalakhov  
Дата: 12.05.10 10:37
Оценка:
Уже лучше, спасибо — секунд 8 против 1, но execution plan всё равно по сравнению с 1м запросом выглядит монстрообразно


SELECT UTC_Time, SC2  
FROM Frames JOIN Science_data ON Frames.id = Science_data.id   
WHERE UTC_time BETWEEN '2009-09-16 21:43:14' AND '2009-09-16 23:43:14' AND GoodToMap = 1

       |--Nested Loops(Inner Join, OUTER REFERENCES:([Frames].[id]) WITH PREFETCH)
       |--Filter(WHERE:([Frames].[GoodToMap]=1))
       |    |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([LEND_FLIGHT].[dbo].[Frames]) WITH PREFETCH)
       |         |--Index Seek(OBJECT:([LEND_FLIGHT].[dbo].[Frames].[IX_UTC]), SEEK:([Frames].[UTC_time] >= 'Sep 16 2009  9:43PM' AND [Frames].[UTC_time] <= 'Sep 16 2009 11:43PM') ORDERED FORWARD)
       |--Clustered Index Seek(OBJECT:([LEND_FLIGHT].[dbo].[Science_data].[PK_Science_data]), SEEK:([Science_data].[id]=[Frames].[id]) ORDERED FORWARD)



SELECT UTC_Time, SC2  
FROM   Frames
              INNER LOOP JOIN Science_data
              ON  Frames.id = Science_data.id  
WHERE UTC_time BETWEEN @curStart AND DATEADD(hour, 2, @curStart) AND GoodToMap = 1


  |--Parallelism(Gather Streams)
       |--Nested Loops(Inner Join, OUTER REFERENCES:([Frames].[id]) WITH PREFETCH)
            |--Sort(ORDER BY:([Frames].[id] ASC))
            |    |--Hash Match(Inner Join, HASH:([Bmk1000])=([Bmk1000]), RESIDUAL:([Bmk1000]=[Bmk1000]))
            |         |--Bitmap(HASH:([Bmk1000]), DEFINE:([Bitmap1005]))
            |         |    |--Parallelism(Repartition Streams, PARTITION COLUMNS:([Bmk1000]))
            |         |         |--Index Seek(OBJECT:([LEND_FLIGHT].[dbo].[Frames].[IX_UTC]), SEEK:([Frames].[UTC_time] >= [@curStart] AND [Frames].[UTC_time] <= dateadd(hour, 2, [@curStart])) ORDERED FORWARD)
            |         |--Parallelism(Repartition Streams, PARTITION COLUMNS:([Bmk1000]), WHERE:(PROBE([Bitmap1005])=TRUE))
            |              |--Index Seek(OBJECT:([LEND_FLIGHT].[dbo].[Frames].[IX_GoodToMap]), SEEK:([Frames].[GoodToMap]=1) ORDERED FORWARD)
            |--Clustered Index Seek(OBJECT:([LEND_FLIGHT].[dbo].[Science_data].[PK_Science_data]), SEEK:([Science_data].[id]=[Frames].[id]) ORDERED FORWARD)


Хотя это видимо уже я пошел читать rtfm про inner loop... Спасибо в любом случае
Re[6]: MSSQL - переменные в WHERE
От: FilosOFF Россия  
Дата: 12.05.10 10:56
Оценка: 23 (2)
Спасибо, обычно, оценками показывается

Теперь по планам. Вы вероломно забили на индексы, и не сказали что они есть!
Так вот, глядя на планы видно что в первом случае используется ТОЛЬКО один индекс IX_UTC а во втором IX_UTC и IX_GoodToMap, а затем идет HASH джоин этих индексов.
Вот так должно быть:
SELECT UTC_Time, SC2  
FROM   Frames WITH (INDEX(IX_UTC))
              INNER LOOP JOIN Science_data
              ON  Frames.id = Science_data.id  
WHERE UTC_time BETWEEN @curStart AND DATEADD(hour, 2, @curStart) AND GoodToMap = 1
... << RSDN@Home 1.2.0 alpha 4 rev. 1231>>
Re[7]: MSSQL - переменные в WHERE
От: amalakhov  
Дата: 12.05.10 11:02
Оценка:
Здравствуйте, FilosOFF, Вы писали:

FOF>Спасибо, обычно, оценками показывается

Угу, увидел

FOF>Теперь по планам. Вы вероломно забили на индексы, и не сказали что они есть!

Это я как-то действительно дал... Но в любом случае — сейчас всё отлично выполняется, спасибо ещё раз (это в дополнение к оценкам ).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.