TSQL не использует индексы - PullRequest
1 голос
/ 12 июля 2011

Это тестовый senario, созданный с временными таблицами для иллюстрации проблемы.Представьте, что таблица @userdata имеет индекс по идентификатору пользователя, а таблица @users имеет индекс по идентификатору

Почему первый выбор не может использовать индекс, я предположил, что он будет работать лучше в 1 подвыборе, чем в 2 подвыборах *

Версия - Microsoft SQL Server 2008 R2 (окончательная первоначальная версия) Уровень совместимости - SQL Server 2000.

-- test tables
DECLARE @userdata TABLE(info VARCHAR(50), userid INT)
DECLARE @users    TABLE(id INT, username VARCHAR(20), superuser BIT)

-- test data
INSERT @users    VALUES(1, 'superuser', 1)
INSERT @users    VALUES(2, 'testuser1', 0)
INSERT @users    VALUES(3, 'testuser2', 0)
INSERT @userdata VALUES('secret information', 1)
INSERT @userdata VALUES('testuser1''s data', 2)
INSERT @userdata VALUES('testuser2''s data', 3)
INSERT @userdata VALUES('testuser2''s data',3)

DECLARE @username VARCHAR(50)
SET @username = 'superuser'
--SET @username = 'testuser1'


--The superuser can read all data
--The testusers can only read own data

-- This sql can't use indexes and is very slow
SELECT *
FROM @userdata d
WHERE EXISTS 
(SELECT 1 FROM @users u
WHERE u.username = @username AND u.superuser = 1 OR 
u.id = d.userid AND u.username = @username)

-- This sql uses indexes and performs well
SELECT *
FROM @userdata d
WHERE EXISTS 
(SELECT 1 FROM @users u
WHERE u.username = @username AND u.superuser = 1)
OR EXISTS (SELECT 1 FROM @users u
WHERE u.ID = d.userid 
AND u.username = @username)

Ответы [ 3 ]

1 голос
/ 12 июля 2011

Я думаю, что or может вызвать проблемы у анализатора запросов, чтобы придумать хороший план запросов. Это на самом деле не ответ на ваш вопрос, а альтернативный способ сделать этот запрос. Помимо уже имеющегося у вас индекса, я бы предложил индекс для @ users.username.

if exists(select * from @users where username = @username and superuser = 1)
begin
  select *
  from @userdata
end
else
begin
  select d.*
  from @userdata as d
    inner join @users as u
      on d.userid = u.id
  where u.username = @username
end
1 голос
/ 15 июля 2011

SQL Server не всегда выдает оптимальный план, когда вы используете локальные переменные (@username в вашем случае).

См. Следующую ссылку для примера, где SQL Server не использует индекс, поскольку используется локальная переменная: http://www.sqlbadpractices.com/using-local-variables-in-t-sql-queries/.

0 голосов
/ 12 июля 2011

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

Вы можете попытаться заставить его использовать индекс .В этом случае запрос может оказаться медленнее.

Вы можете попробовать ALTER INDEX ixFoo REBUILD, чтобы перестроить индекс.Индекс может не использоваться, поскольку он чрезмерно фрагментирован.

Вы также можете попробовать UPDATE STATISTICS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...