2016-04-20 4 views
0

У меня есть представление с двумя отдельными запросами с объединением всех. Например:Как оптимизировать просмотр с помощью Union All

CREATE VIEW MyView AS 

SELECT foo.id, bar.data 
FROM foo 
INNER JOIN bar ON foo.id = bar.id 

UNION ALL 

SELECT baz.id, baz.data 
FROM baz 

Я затем запустить отборное заявление против того, как это:

SELECT * FROM MyView WHERE id = 1 

Идентификатор 1 существует только в первом отборного заявления. Тот, который имеет таблицы foo и bar, но соединение с таблицей baz по-прежнему вызывает замедление работы. Это быстрее, если вывести союз. Я должен оставить его там, потому что иногда будет использоваться идентификатор, который будет возвращать результаты из второго оператора select.

Мой вопрос: есть ли способ помочь серверу sql знать, что во второй части союза нет результатов, поэтому ему не нужно запускать этот запрос?

Все эти данные были в одной таблице. Это новая структура данных, и все наши старые приложения будут полагаться на это представление для чтения данных из этой новой структуры данных. Вот почему мы не знаем, какая таблица будет на самом деле иметь результаты заранее.

+0

Если вы знаете заранее строки вы ищете от первой таблицы, запроса, непосредственно – Amit

+0

Кстати, если вы реальный запрос похож на это, даже не включать 'foo', использовать' bar' напрямую, у него есть все необходимые данные. – Amit

+0

Нет, это просто пример. В действительности есть поля, которые нам нужны из обеих таблиц. Я сделал править, объясняя, почему я не знаю заранее, какая таблица будет иметь нужный нам результат. – rgvassar

ответ

0

Существует способ сделать условное объединение соединения. Попытайтесь выяснить, помогает ли это ускорить запрос, просмотрев план выполнения. Может быть, ваша шея бутылки не совсем там, где вы думаете?

SELECT foo.id, bar.data 
FROM foo 
INNER JOIN bar ON foo.id = bar.id 

UNION ALL 

SELECT baz.id, baz.data 
FROM baz 
WHERE baz.id = @idSearched 

Sproc с параметром может сделать трюк вместо представления, если вы не собираетесь редактировать.

CREATE PROCEDURE procName 
-- Add the parameters for the stored procedure here 
@id INT = 1 
AS 
BEGIN 
SET NOCOUNT ON; 

SELECT foo.id, bar.data 
FROM foo 
INNER JOIN bar ON foo.id = bar.id 

UNION ALL 

SELECT baz.id, baz.data 
FROM baz 
WHERE baz.id = @id 
END 
GO 

Если вы абсолютно необходимо представление, как таблицы, осуществлять хранимую функцию в следующем виде формата:

CREATE FUNCTION v_emp (@pintEno INT) 
RETURNS TABLE 
AS 
RETURN 
    SELECT * FROM emp WHERE [email protected]; 
This allows you to use it as a normal view, with: 
--Query it like : 
SELECT * FROM v_emp(10) 
+0

Все ваши решения потребуют от меня переписать каждое приложение, которое обращается к этому представлению, чтобы в принципе не использовать представление. Это не то, что я могу сделать прямо сейчас. Я ищу способ оптимизировать представление и вернуть ему те же результаты, что и сейчас. – rgvassar

+0

Каков результат вашего плана выполнения? Функция create может полностью заменить ваш взгляд, если вы назовете его одним и тем же. – WickedFan

+0

Также смотрите в раздел HAVING. SELECT * FROM MyView HAVING id = 1 Сравнить планы выполнения – WickedFan

-1

У вас есть индекс по baz(id)? Я бы ожидать, индекс будет использоваться для этого запроса:

SELECT foo.id, bar.data 
FROM foo 
INNER JOIN bar ON foo.id = bar.id 
UNION ALL 
SELECT baz.id, baz.data 
FROM baz 
WHERE baz.id; 
+0

Да, это первичный ключ, поэтому на нем есть кластерный индекс. Тем не менее, он имеет около 16 миллионов записей, поэтому он все еще немного замедляет запрос. Я надеялся, что есть какой-то способ понять, что вообще не нужно запускать эту часть запроса. – rgvassar

+0

Это идентично тому, что было представлено выше. См. SQL, встроенный в sproc. – WickedFan

+0

@ rgvassar. , , Как это замедляет запрос?Поиск записи в индексе первичного ключа и * не * поиск его занимает очень мало времени. Какую разницу в производительности вы видите? –

Смежные вопросы