Создание таблицы, которая обобщает данные о другой таблице. Предложения по оптимизации? - PullRequest
0 голосов
/ 02 августа 2011

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

Я создал временную таблицу с именем @currentpages, которая содержит 55 тыс. Строк и выглядит следующим образом:

DECLARE @currentpages table(
ContentID       NUMERIC(19,0) NOT NULL PRIMARY KEY,
PageTitle       VARCHAR(255) NULL,
SpaceKey            VARCHAR(255) NULL,
OriginalAuthor  VARCHAR(255) NULL,
LastChangedBy   VARCHAR(255) NULL,
LastChangedDt   VARCHAR(10) NULL,
ContentBody         TEXT NULL); 

и еще одна таблица, которая выглядит так:

DECLARE @usage table(
SpaceKey        VARCHAR(255) NOT NULL PRIMARY KEY,
Macro1      NUMERIC(19,0) NULL,
Macro2      NUMERIC(19,0) NULL,
Macro3              NUMERIC(19,0) NULL);

(я упростил вышеизложенное; на самом деле он содержит около 40 столбцов, таких как Macro1, Macro2 и т. Д.) Я пытаюсь получить количество ссылок (в @currentpages) на эти различные макросы. *

Я инициализирую таблицу @usage, создавая строку для каждого возможного значения SpaceKey, обнуляя все счетчики макросов "x":

INSERT INTO @usage (SpaceKey, Macro1, Macro2, Macro3)
SELECT S.spacekey, 0, 0, 0
FROM spaces     S
ORDER BY S.spacekey

Затем я запускаю первый из нескольких операторов UPDATE, чтобы идентифицировать каждую ссылку на макрос:

UPDATE @usage
SET U.AdvancedSearch = C.Counter
FROM @usage                 U
INNER JOIN (SELECT SpaceKey, COUNT(*) AS Counter 
    FROM @currentpages 
    WHERE ContentBody LIKE '%{search-%' GROUP BY SpaceKey) C 
        ON U.SpaceKey = C.SpaceKey

Кажется, это работает нормально, но работает очень долго. Есть ли более эффективный способ сделать то, что я пытаюсь сделать?

Эта база данных находится на SQL Server 2005.

Большое спасибо, Бетси

Ответы [ 3 ]

1 голос
/ 03 августа 2011
  1. Исследовать полнотекстовый поиск.( Полнотекстовый поиск @ MSDN ) У меня нет с этим никакого опыта, поэтому я не могу дать совет.

  2. Вместо того, чтобы запрашивать @CurrentPages один раз для макроса,получить все макрокоманды сразу.Что-то вроде:

    INSERT INTO @usage (SpaceKey, Macro1, Macro2, Macro3)
    SELECT S.spacekey
        , count(case when ContentBody LIKE '%Search Macro 1%' 
            then 1 else null end) as Macro1_Count
        , count(case when ContentBody LIKE '%Search Macro 2%' 
            then 1 else null end) as Macro2_Count
        , count(case when ContentBody LIKE '%Search Macro 3%' 
            then 1 else null end) as Macro=3Count
    FROM spaces S
    LEFT OUTER JOIN @CurrentPages C ON C.SpaceKey = S.SpaceKey
    GROUP BY S.spacekey
    
0 голосов
/ 02 августа 2011

Не делайте столбец для каждого макроса, а создайте таблицу, подобную этой.

DECLARE @macrotype table(
    type      int          NOT NULL PRIMARY KEY
  , MacroName varchar(100) NOT NULL 
  , mask      varchar(100) NOT NULL 
)

DECLARE @usage table(
  SpaceKey    VARCHAR(255) NOT NULL PRIMARY KEY,
, MacroType   int NOT NULL 
, MacroCount  int NOT NULL 
)

Если у вас есть это, вы можете заполнить его, запустив

  INSERT INTO @macrotype VALUES (1, 'search', '%{search-%')
                              , (2, 'yadayada', '%{yadayada-%')
                              , ...

  DECLARE @c int, @m varchar(100)
  DECLARE c CURSOR READ_ONLY FOR SELECT type, mask FROM @macrotype
  OPEN c

  FETCH NEXT FROM c INTO @t, @m

  WHILE @@FETCH_STATUS = 0 
    BEGIN
      INSERT INTO @usage (SpaceKey, MacroType, MacroCount)
      SELECT SpaceKey
           , @t
           , COUNT(*) AS Counter 
        FROM @currentpages
       WHERE ContentBody LIKE @m
    GROUP BY SpaceKey
    FETCH NEXT FROM c INTO @t, @m
  END
  CLOSE c
  DEALLOCATE c

В конце своей истории вы можете запросить таблицу @usage, чтобы подсчитать в любой форме.

  SELECT MacroName, count = count(*)
    FROM @usage u
    JOIN @macrotype m
      ON u.MacroType - m.type
GROUP BY MacroName

На 55k записях это будет продолжаться в течение нескольких минут.

0 голосов
/ 02 августа 2011

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

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

...