在大型sql server表上查找的最佳解决方案

时间:2013-01-18 18:55:31

标签: vb.net sql-server-2008 hashtable

我有一个用户ID的大表和另一个用户记录表,其中包含一个用户ID的用户帖子。这个过程是每当检索到一个新的feed帖子时,我都会向用户id表请求一个标记为inactive的id(我有那个字段ACTIVE,因为我有另一个创建这些id的进程并将其连续插入到表1中)当请求id时,它被标记为非活动状态。 然后我检查用户表(表2)中是否存在用户,如果是,则返回与该用户关联的用户ID。

有人告诉我,我可以加快这个过程,但是创建一个哈希表来对表2进行查找。我不知道如何开始这个,任何链接或样本将不胜感激。 此外,我需要运行一个单独的进程来清除表1并删除所有非活动用户ID。

当我调用插入表2的过程时,我传递了从表1中检索到的用户ID。

CREATE TABLE [dbo].[userforums]
  (
     [userid]       [VARCHAR](16) NOT NULL  CONSTRAINT [PK_forumssiteid] PRIMARY KEY CLUSTERED ,
     [forumname]    [VARCHAR](500) NOT NULL,
     [exported]     [INT] NULL,
     [lastcrawled]  [DATETIME] NULL,
     [priority]     [INT] NULL,
     [origin]       [VARCHAR](50) NULL,
     [queryid]      [VARCHAR](25) NULL,
     [dateinserted] [DATETIME] NULL DEFAULT (getdate()) 
   )

第二张表

CREATE TABLE [dbo].[userids]
  (
     [userid] [NVARCHAR](20) NOT NULL CONSTRAINT [PK_userids] PRIMARY KEY CLUSTERED,
     [active] [NVARCHAR](20) NULL  CONSTRAINT [IX_userids] UNIQUE NONCLUSTERED 
  )

获取用户ID存储过程

BEGIN TRANSACTION

SELECT TOP 1 @id = userid
FROM   userids WITH (UPDLOCK, HOLDLOCK)
WHERE  active = 'Y'
        OR active IS NULL

UPDATE userids
SET    active = 'N'
WHERE  userid = @id

COMMIT TRANSACTION 

检查用户ID是否存在

CREATE PROC Foo @forumname VARCHAR(500),
                @userid    VARCHAR(16),
                @origin    VARCHAR(50),
                @queryid   VARCHAR(25)
AS
    SET NOCOUNT ON;

    DECLARE @cnt INT
    DECLARE @serverip VARCHAR(16)
    DECLARE @mincnt INT
    DECLARE @siteservercnt INT

    SELECT @cnt = COUNT(*)
    FROM   userforums
    WHERE  forumname = @forumname

    IF @cnt = 0
      BEGIN
          INSERT INTO userforums
                      (forumname,
                       userid,
                       exported,
                       origin,
                       queryid)
          VALUES     (@forumname,
                      @userid,
                      1,
                      @origin,
                      @queryid)

          SELECT @siteservercnt = COUNT(*)
          FROM   siteserverip
          WHERE  userid = @userid

          IF @siteservercnt = 0
            BEGIN
                SELECT TOP 1 @mincnt = COUNT(*),
                             @serverip = serverip
                FROM   siteserverip
                GROUP  BY serverip
                ORDER  BY COUNT(*)

                SELECT TOP 1 @mincnt = sitecount,
                             @serverip = serverip
                FROM   serveripcounts
                ORDER  BY sitecount

                INSERT INTO siteserverip
                VALUES     (@siteid,
                            @serverip)

                UPDATE serveripcounts
                SET    sitecount = sitecount + 1
                WHERE  serverip = @serverip
            END
      END

    SELECT userid
    FROM   userforums
    WHERE  forumname = @forumname

    RETURN 

2 个答案:

答案 0 :(得分:2)

您现有的出列查询可以改进。而不是

DECLARE @id INT

SELECT TOP 1 @id = userid
FROM   userids WITH (UPDLOCK, HOLDLOCK)
WHERE  active = 'Y'
        OR active IS NULL

UPDATE userids
SET    active = 'N'
WHERE  userid = @id

您可以执行两项操作(聚簇索引扫描后跟索引查找)

UPDATE TOP (1) userids  
WITH (ROWLOCK, READPAST)
SET  active = 'N'
OUTPUT INSERTED.userid
WHERE  active <> 'N'

这是一项操作,并给出了两个范围寻求的计划。

答案 1 :(得分:-1)

哈希表#TableName是tempdb中用作表的临时对象。它们通常被称为“临时表”。如果这是常见的情况,我不会将它们用作动态检索数据的第一个解决方案。相反,我会创建一个索引,看看是否能证明你的需要。通常,哈希表用于强烈的操作,在这种操作中,您希望获得一组可能会或可能不会被索引的内容,然后将其与其他内容相关联,并且您希望将其保留在内存中。

我会创建一个索引,这应该可以提高速度。此外,如果您发现速度很慢,则哈希表不会加快该部分的速度,它只是将其集合放入源中以便从主表中重复使用。

create index IX_[yourtableName]_[TableColumn(s)] on [Tablename]([Column(s)]

除非必要,否则我不会创建更多对象。通常,如果您的UserId是有效的整数,您可以非常快速地搜索它们。