构建一个汇总另一个表数据的表 - 优化建议?

时间:2011-08-02 13:01:47

标签: sql-server-2005 tsql sql-optimization

我正在尝试构建一个表,该表总结了Wiki中的页面引用某些宏的次数。

我已经构建了一个名为@currentpages的临时表,其中包含55k行,如下所示:

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中)到这些不同的宏。

我通过为每个可能的SpaceKey值创建一行来初始化@usage表,将所有宏“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 个答案:

答案 0 :(得分:1)

  1. 调查全文搜索。 (Full Text Search @ 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
    

答案 1 :(得分:0)

我认为任何性能命中都会来自包含LIKE子句的子查询,因为它将进行全表扫描。我真的没有看到还有什么会减慢这一点。

您可以通过仅运行子查询并比较返回到您的某个列的整个更新所需的时间来测试它。

答案 2 :(得分:0)

不要为每个宏创建一个列,而是创建一个这样的表。

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记录中,这将持续几分钟。