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

Откуда: Київ
Сообщений: 10428
Есть такой запрос во вью

SELECT  id, type, parent_id
FROM	[dbo].[v5] with(nolock)
WHERE 
(
	USER_ID() = 1
	OR
		(
			v5.type IN (1,2,3)
			and 
			EXISTS
			(
					SELECT obj_id FROM dbo.access with(nolock) 
					where  access.obj_id = id 
					AND obj_id.[u_name] in 
					(
						select SUSER_SNAME() union all 
						select [name] COLLATE database_default from dbo.u_role
					)
			)
		)
)



на больших базах он выполняется 25 сек.
Если я для эксперимента закрываю комментарием
	USER_ID() = 1
	OR

тогда - 5 сек.

Не соображу, как его переделать?
13 июн 13, 10:41    [14426698]     Ответить | Цитировать Сообщить модератору
 Re: Как переделать запрос, чтобы выполнялся быстрее?  [new]
_djХомяГ
Guest
Классически - прописать не через OR а через UNION/UNION ALL
13 июн 13, 10:47    [14426725]     Ответить | Цитировать Сообщить модератору
 Re: Как переделать запрос, чтобы выполнялся быстрее?  [new]
iap
Member

Откуда: Москва
Сообщений: 47083
Winnipuh,

в dbo.access есть поле id?
Что-то Вы на алиасы забили...
13 июн 13, 11:12    [14426919]     Ответить | Цитировать Сообщить модератору
 Re: Как переделать запрос, чтобы выполнялся быстрее?  [new]
MasterZiv
Member

Откуда: Питер
Сообщений: 34696
_djХомяГ
Классически - прописать не через OR а через UNION/UNION ALL


Субд скорее всего и так это делает.

А вот что не надо делать distinct после union точно не догадаться, так что если это ваш случай, переписывание через union all должно немного помочь.
13 июн 13, 11:16    [14426952]     Ответить | Цитировать Сообщить модератору
 Re: Как переделать запрос, чтобы выполнялся быстрее?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
iap
Winnipuh,

в dbo.access есть поле id?
Что-то Вы на алиасы забили...



сделал простой запрос из реального, там еще круче наверчено, но id это из верхнего v5
13 июн 13, 11:21    [14426997]     Ответить | Цитировать Сообщить модератору
 Re: Как переделать запрос, чтобы выполнялся быстрее?  [new]
iap
Member

Откуда: Москва
Сообщений: 47083
Winnipuh
iap
Winnipuh,

в dbo.access есть поле id?
Что-то Вы на алиасы забили...



сделал простой запрос из реального, там еще круче наверчено, но id это из верхнего v5
Я про dbo.access спрашивал.
Наверно, сами понимаете что будет, если и в ней id имеется...
13 июн 13, 11:23    [14427019]     Ответить | Цитировать Сообщить модератору
 Re: Как переделать запрос, чтобы выполнялся быстрее?  [new]
MasterZiv
Member

Откуда: Питер
Сообщений: 34696
Winnipuh,

Это у вас row wise access?
Совет такой — упрощайте все до одного единственного случая, без исключений, тогда у вас будет один только exists.
У вас должно остаться одно единственное правило, простое и тупое, только тогда это будет работать.

Права не денормализуйте, если данных много.
13 июн 13, 11:24    [14427027]     Ответить | Цитировать Сообщить модератору
 Re: Как переделать запрос, чтобы выполнялся быстрее?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
MasterZiv
Winnipuh,

Это у вас row wise access?
Совет такой — упрощайте все до одного единственного случая, без исключений, тогда у вас будет один только exists.
У вас должно остаться одно единственное правило, простое и тупое, только тогда это будет работать.

Права не денормализуйте, если данных много.


да, мягко выражаясь

По идее я так понимаю надо что-то типа такого

select * from...
where user_id()=1
union all 
select * from...
where 
( user_id()<>1 and ....)



т.е. если user_id() выдает все записи и не выполняется второй запрос в юнионе и наоборот.
Но тогда надо во втором ставить тоже проверку user_id()<>1, а так тоже фигня получится, шило на мыло....
13 июн 13, 11:28    [14427062]     Ответить | Цитировать Сообщить модератору
 Re: Как переделать запрос, чтобы выполнялся быстрее?  [new]
Andrey Sribnyak
Member

Откуда: Киев
Сообщений: 599
_djХомяГ
Классически - прописать не через OR а через UNION/UNION ALL


А разве тогда не будет двух сканирований таблицы? что при очень больших данных может быть вдвое медленней?
13 июн 13, 11:56    [14427321]     Ответить | Цитировать Сообщить модератору
 Re: Как переделать запрос, чтобы выполнялся быстрее?  [new]
Winnipuh
Member [заблокирован]

Откуда: Київ
Сообщений: 10428
iap
Winnipuh
пропущено...



сделал простой запрос из реального, там еще круче наверчено, но id это из верхнего v5
Я про dbo.access спрашивал.
Наверно, сами понимаете что будет, если и в ней id имеется...


да, согласен. там нету.
13 июн 13, 11:59    [14427338]     Ответить | Цитировать Сообщить модератору
 Re: Как переделать запрос, чтобы выполнялся быстрее?  [new]
Mikebond
Member

Откуда: Киев
Сообщений: 32
Winnipuh

т.е. если user_id() выдает все записи и не выполняется второй запрос в юнионе и наоборот.
Но тогда надо во втором ставить тоже проверку user_id()<>1, а так тоже фигня получится, шило на мыло....


Вариант №1 :
"Union all" -хорошо, но и "if ... then ... else ...." никто не отменял :

if user_id()=1 
        SELECT  id, type, parent_id
        FROM    [dbo].[v5] with(nolock)
Else 
  select ....

Результат такого запроса можно предварительно сохранить в табличную переменную и использовать в более сложном запросе. В результате если безусловный селект выполняется быстрее чем с условием, но без "user_id() = 1 or" , то максимальное время выполнения сокращается до 5 секунд. "Exists(..." можно попробовать заменить на "join (select distinct obj_id... ) a ", но не могу точно сказать будет ли так ещё быстрее, надо пробовать.

Вариант №2 :
Переменная лучше чем вызов функции:

Если вариант №1 не подходит, то можно попробовать предварительно занести значение
user_id() в переменную и использовать в селекте её . Но, опять же, сравнивать константу с константой в "Where" - не лучшее решение.

Как-то так ...
14 июн 13, 01:13    [14431397]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить