MS SQL. Понизить приоритет условия.
От: jedi Мухосранск  
Дата: 23.02.11 12:28
Оценка:
Всем привет,

возникла следующая проблема с написание правильного запроса к MS SQL.
Очень упрощенно ситуация выглядит так:
есть таблица с множеством полей, среди прочих есть spatial поле (Point).

Далее, нужно сделать выборку по ряду условий, среди которых есть также условия попадания Point в заданную область.
Упрощенно запрос выглядит так:

SELECT
    *
FROM
    T
WHERE
    T.A = SomeValue AND
    T.B IN (SomeSubquery) AND
    ... AND
    T.Z = AnotherValue AND
    @Area.STIntersects(T.Point)


Spatial индекса по полю Point по ряду причин, одна из которых — очень частое обновление этого поля, индекс очень долго обновляется.

Я хочу, чтобы в начале проверялись все условия, кроме последнего — в результате должен быть получен очень небольшой набор записей, который уже затем будет отфильтрован по последнему условию.

На практике же происходит обратное — согласно плану MS SQL сперва сканирует всю таблицу и фильтрует ее по @Area.STIntersects, а потом выбрасывает 99% результатов по остальным условиям. Получается очень долго.

В связи с этим вопрос — как мне ему сказать, чтобы @Area.STIntersects проверялось в последнюю очередь?

Заранее спасибо
Re: MS SQL. Понизить приоритет условия.
От: Sergei MO Россия  
Дата: 23.02.11 21:04
Оценка:
Здравствуйте, jedi, Вы писали:

J>Упрощенно запрос выглядит так:


J>
J>SELECT
J>    *
J>FROM
J>    T
J>WHERE
J>    T.A = SomeValue AND
J>    T.B IN (SomeSubquery) AND
J>    ... AND
J>    T.Z = AnotherValue AND
J>    @Area.STIntersects(T.Point)
J>


J>На практике же происходит обратное — согласно плану MS SQL сперва сканирует всю таблицу и фильтрует ее по @Area.STIntersects, а потом выбрасывает 99% результатов по остальным условиям. Получается очень долго.


Если из запроса убрать условие AND @Area.STIntersects(T.Point), то план меняется, и запрос начинает выполняться быстрее?
Re: MS SQL. Понизить приоритет условия.
От: avpavlov  
Дата: 23.02.11 21:17
Оценка: 1 (1)
1) подзапросы и/или ЦТЕ — но не факт что поможет, оптимизатор МС СКЛ и не таких хитрых видал
2) загонять "быстые" результаты во временную таблицу, и потом уже на неё применять "медленный" фильтр
3) хинтами заставить использовать другой индекс, если есть
Re[2]: MS SQL. Понизить приоритет условия.
От: jedi Мухосранск  
Дата: 23.02.11 21:18
Оценка:
Здравствуйте, avpavlov, Вы писали:

A>2) загонять "быстые" результаты во временную таблицу, и потом уже на неё применять "медленный" фильтр


Я так и сделал на данный момент, и получил увеличение скорости раз в десять. Но мне это решение не нравится. Думаю, не надо объяснять почему
Re[2]: MS SQL. Понизить приоритет условия.
От: jedi Мухосранск  
Дата: 23.02.11 21:21
Оценка:
Здравствуйте, Sergei MO, Вы писали:

SM>Если из запроса убрать условие AND @Area.STIntersects(T.Point), то план меняется, и запрос начинает выполняться быстрее?


Да, намного быстрее. Как я уже написал ниже — если сохранить результаты запроса без последнего условия во временную таблицу, а затем выбирать из нее уже — то получается серьезное ускорение. Но это из разряда хаков. Хотелось бы найти цивилизованный способ указать серверу, что я от него хочу.
Re: MS SQL. Понизить приоритет условия.
От: rm822 Россия  
Дата: 24.02.11 07:39
Оценка:
во первых проверь IO

set statistics io on
запрос с хинтами
запрос без хинтов

если без хинтов IO меньше — сиквел прав, просто у тебя база слишком маленькая
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: MS SQL. Понизить приоритет условия.
От: jedi Мухосранск  
Дата: 24.02.11 08:08
Оценка: +1
Здравствуйте, rm822, Вы писали:

R>во первых проверь IO


R>set statistics io on

И? Я по-моему писал, что внимательно изучил план запроса.

R>запрос с хинтами

R>запрос без хинтов

Вот я и пытаюсь понять какие же хинты ему нужны, чтобы он оставил проверку дорогого условия напоследок.

R>если без хинтов IO меньше — сиквел прав, просто у тебя база слишком маленькая


Вам не кажется что это бред? Меня не интересует сферическая правота сиквела в вакууме, меня интересует производительность, которую видят наши клиенты. Так вот с его "правильным решением" запрос выполняется 5-7 секунд, а с моим уродским рукопашным с привлечением временной таблицы < 500 ms. Думаю дальнейшие разговоры о правоте можно оставить.
Re: MS SQL. Понизить приоритет условия.
От: Vyacheslav Benedichuk Интернет  
Дата: 24.02.11 08:15
Оценка:
Попробуй так

SELECT
*
FROM
(
SELECT * FROM
T
WHERE
T.A = SomeValue AND
T.B IN (SomeSubquery) AND
... AND
T.Z = AnotherValue) subq
WHERE
@Area.STIntersects(subq.Point)
--
http://www.slideshare.net/vyacheslavbenedichuk
https://www.linkedin.com/in/vbenedichuk
Re[2]: MS SQL. Понизить приоритет условия.
От: jedi Мухосранск  
Дата: 24.02.11 08:16
Оценка:
VB>SELECT
VB> *
VB>FROM
VB>(
VB>SELECT * FROM
VB> T
VB>WHERE
VB> T.A = SomeValue AND
VB> T.B IN (SomeSubquery) AND
VB> ... AND
VB> T.Z = AnotherValue) subq
VB>WHERE
VB> @Area.STIntersects(subq.Point)

Спасибо, пробовал. На самом деле это один и тот же запрос, с точки зрения сервера
Re[3]: MS SQL. Понизить приоритет условия.
От: Vyacheslav Benedichuk Интернет  
Дата: 24.02.11 08:29
Оценка: 1 (1)
Здравствуйте, jedi, Вы писали:

J>Спасибо, пробовал. На самом деле это один и тот же запрос, с точки зрения сервера

Тогда глянь в хелпе на хинты USE PLAN..., WITH INDEX...
ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.en/s10de_4deptrbl/html/d3a23cac-20c5-42e2-b2e2-bb64237ca4dd.htm
ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.en/s10de_6tsql/html/8bf1316f-c0ef-49d0-90a7-3946bc8e7a89.htm

Может быть помогут.

Еще можно посмотреть раздел Plan Guides, но с этим не уверен.
ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.en/s10de_4deptrbl/html/567df65f-4095-42d8-be19-37e300528c45.htm

Ну и как вариант грязного хака — в тот запрос, что я писал добавить в подзапрос выборку столбца ROW_NUMBER ( ) ... as RN и во внешнем запросе добавить условие subq.RN>0.
Возможно планировщик передумает.
--
http://www.slideshare.net/vyacheslavbenedichuk
https://www.linkedin.com/in/vbenedichuk
Re[4]: MS SQL. Понизить приоритет условия.
От: jedi Мухосранск  
Дата: 24.02.11 08:38
Оценка:
Здравствуйте, Vyacheslav Benedichuk, Вы писали:

VB>Ну и как вариант грязного хака — в тот запрос, что я писал добавить в подзапрос выборку столбца ROW_NUMBER ( ) ... as RN и во внешнем запросе добавить условие subq.RN>0.

VB>Возможно планировщик передумает.

Спасибо за попытку помочь
Грязные хаки я изобретать умею — на данный момент таким грязным хаком в виде временной таблицы и обошелся.

Мне все же хотелось найти "правильное" решение проблемы, но его видимо просто не существует
Re[5]: MS SQL. Понизить приоритет условия.
От: Vyacheslav Benedichuk Интернет  
Дата: 24.02.11 08:42
Оценка:
Здравствуйте, jedi, Вы писали:

J>Спасибо за попытку помочь

J>Грязные хаки я изобретать умею — на данный момент таким грязным хаком в виде временной таблицы и обошелся.

J>Мне все же хотелось найти "правильное" решение проблемы, но его видимо просто не существует


Да незачто. Если найдешь — поделись. Интересно.
--
http://www.slideshare.net/vyacheslavbenedichuk
https://www.linkedin.com/in/vbenedichuk
Re[3]: MS SQL. Понизить приоритет условия.
От: rm822 Россия  
Дата: 24.02.11 09:23
Оценка: -1
чувак, мне пофиг что ты думаешь по поводу того как должен работать сиквел и как ты там изучал план
я задал простой вопрос, IO в каком случае больше?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: MS SQL. Понизить приоритет условия.
От: Sergei MO Россия  
Дата: 24.02.11 09:39
Оценка:
Здравствуйте, jedi, Вы писали:

J>Здравствуйте, Sergei MO, Вы писали:


J>Как я уже написал ниже — если сохранить результаты запроса без последнего условия во временную таблицу, а затем выбирать из нее уже — то получается серьезное ускорение. Но это из разряда хаков. Хотелось бы найти цивилизованный способ указать серверу, что я от него хочу.


Если я правильно понял, @Area — это довольно сложный объект, и вызов STIntersects сам по себе занимает много времени. В таком случае промежуточная таблица — это вполне нормальный способ, и боюсь, что единственный из цивилизованных.

Если таблица не нравится, могу предложить ещё такой хак. Нужно создать вспомогательную таблицу:

CREATE TABLE One
(
    Value INT NOT NULL
)

INSERT INTO One VALUES (1)


А запрос изменить так:

SELECT *
FROM
(
    SELECT
        *
    FROM
        T
    WHERE
        T.A = SomeValue AND
        T.B IN (SomeSubquery) AND
        ... AND
        T.Z = AnotherValue
) Q
INNER JOIN One
    ON @Area.STIntersects(Q.Point) = One.Value
OPTION (FORCE ORDER)
Re[3]: MS SQL. Понизить приоритет условия.
От: avpavlov  
Дата: 24.02.11 10:58
Оценка:
Здравствуйте, jedi, Вы писали:

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


A>>2) загонять "быстые" результаты во временную таблицу, и потом уже на неё применять "медленный" фильтр


J>Я так и сделал на данный момент, и получил увеличение скорости раз в десять. Но мне это решение не нравится. Думаю, не надо объяснять почему


попробуй CTE, где-то там внутри будет почти тоже самое что и временные таблицы.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.