2012-02-13 3 views
2

У моего сайта есть процедура поиска, которая выполняется очень медленно. Одна вещь, которая замедляет ее, - это соединение в 8 таблиц, которое она должна выполнить (она также содержит предложение WHERE по ~ 6 параметрам поиска). Я попытался сделать запрос быстрее, используя различные методы, такие как добавление индексов, но это не помогло.Кэширование объединенных таблиц в SQL Server

Одна идея У меня есть кэширование результата объединения 8 таблиц. Я мог бы создать временную таблицу соединения и заставить процедуру поиска запросить эту таблицу. Я мог обновлять таблицу каждые 10 минут или около того.

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

IF CachedTable is NULL or CachedTable is older than 10 minutes 
    DROP TABLE CachedTable 
    CREATE TABLE CachedTable as (select * from .....) 
ENDIF 

Select * from CachedTable Where Name = @SearchName 
          AND EmailAddress = @SearchEmailAddress 

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

Кроме того, это может занять довольно много времени, чтобы сделать новый CachedTable каждый раз, так что я думал о попытке что-то вроде двойной буферизации в компьютерной графике:

IF CachedTabled is NULL 
    CREATE TABLE CachedTable as (select * from ...) 
ELSE IF CachedTable is older than 10 minutes 
    -- Somehow do this asynchronously, so that the next time a search comes 
    -- through the new table is used? 
    ASYNCHRONOUS (
     CREATE TABLE BufferedCachedTable as (select * from ...) 
     DROP TABLE CachedTable 
     RENAME TABLE BufferedCachedTable as CachedTable 
    ) 

Select * from CachedTable Where Name = @SearchName 
          AND EmailAddress = @SearchEmailAddress 

Есть ли в этом смысл? Если да, то как мне это достичь? Если нет, что мне делать вместо этого? Я попытался использовать индексированные представления, но это привело к странным ошибкам, поэтому я хочу что-то вроде этого, что я могу иметь больше контроля (также, что-то, что я могу потенциально открутить на другой сервер в будущем.)

Кроме того, как насчет индексов и т. д. для таблиц, созданных таким образом?

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

+0

Вам нужен скрипт в индексы, ограничения и т. д. Они не поставляются с новой таблицей бесплатно, когда вы используете 'SELECT INTO' и т. д. –

ответ

5

Вы можете использовать несколько схем (вы всегда должны указывать схему!) И играть в switch-a-roo, как я продемонстрировал в this question. В основном вам нужны две дополнительные схемы (одна для временного хранения копии таблицы и одна для хранения кешированной копии).

CREATE SCHEMA cache AUTHORIZATION dbo; 
CREATE SCHEMA hold AUTHORIZATION dbo; 

Теперь создайте подражание таблицы в схеме кэша:

SELECT * INTO cache.CachedTable FROM dbo.CachedTable WHERE 1 = 0; 
-- then create any indexes etc. 

Теперь, когда приходит время, чтобы обновить данные:

-- step 1: 
TRUNCATE TABLE cache.CachedTable; 
-- (if you need to maintain FKs you may need to delete) 
INSERT INTO cache.CachedTable SELECT ... 

-- step 2: 
-- this transaction will be almost instantaneous, 
-- since it is a metadata operation only: 

BEGIN TRANSACTION; 
    ALTER SCHEMA hold TRANSFER dbo.Cachedtable; 
    ALTER SCHEMA dbo TRANSFER cache.CachedTable; 
    ALTER SCHEMA cache TRANSFER hold.CachedTable; 
COMMIT TRANSACTION; 
+0

Спасибо, это выглядит довольно элегантно. Кажется, я не использую схемы на данный момент (все просто dbo. [TableName]). – Oliver

+0

Вы должны по-прежнему указывать 'dbo.CachedTable' в своем запросе, а не' CachedTable' - http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/11/bad-habits-to-kick-avoiding- the-schema-prefix.aspx –

+0

У меня сейчас это работает, и он работает очень хорошо, спасибо за вашу помощь. – Oliver

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