0

ユーザーIDの大きなテーブルと、ユーザーIDを持つユーザー投稿を含むユーザーレコードの別のテーブルがあります。このプロセスは、新しいフィード投稿が取得されるたびに、非アクティブとマークされている ID をユーザー ID テーブルに要求します (これらの ID を作成してテーブル 1 に継続的に挿入する別のプロセスがあるため、そのフィールドは ACTIVE です)。 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()) 
   )

2番目のテーブル

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 
4

2 に答える 2

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

これは、実行できる 2 つの操作 (クラスター化されたインデックス スキャンとそれに続くインデックス シーク) です。

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

これは 1 つの操作であり、2 つのレンジ シークを含むプランを提供します。

于 2013-01-18T21:00:43.970 に答える
-1

ハッシュテーブル#TableNameは、テーブルとして機能するtempdbの一時オブジェクトです。それらは一般に「一時テーブル」と呼ばれます。これが一般的な発生である場合、その場でデータを取得するための最初のソリューションとしてそれらを使用することはありません。代わりに、インデックスを作成して、それがあなたのニーズを正当化するかどうかを確認します。一般に、ハッシュテーブルは、インデックス付けされている場合とされていない場合がある一連の項目を取得し、それを他の何かに関連付けてメモリに保持したいという集中的な操作に使用されます。

インデックスを作成すると、速度が向上するはずです。また、遅いとわかった場合、ハッシュテーブルはその部分を高速化せず、メインテーブルから分離して再利用するためにそのコレクションをソースに配置するだけです。

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

必要な場合を除いて、これ以上オブジェクトを作成することはありません。一般に、UserIdが有効なintである場合、それらを非常に高速に検索できます。

于 2013-01-18T20:07:36.577 に答える