3

現在、C#でWebクローラーを構築中です。まだクロールされていないURLをキューに入れるには、SQL Serverを使用します。それはかなり高速に動作しますが、時間の経過とともに大きくなってストアドプロシージャを遅くします。SQL Serverの優先キュー

CREATE TABLE PriorityQueue 
(
ID int IDENTITY(0,1) PRIMARY KEY, 
absolute_url varchar (400), 
depth int, 
priorty int, 
domain_host varchar (255), 
); 

CREATE INDEX queueItem ON PriorityQueue(absolute_url); 
CREATE INDEX queueHost ON PriorityQueue(domain_host); 

これは私のキューに使用するテーブルです。 1から5までの優先順位番号.1が最も高い優先順位です。ご覧のとおり、私はまた、私のストアドプロシージャのインデックスを下に使います。キューに新しいアイテムを追加するための

手順:

DROP PROCEDURE IF EXISTS dbo.Enqueue 
GO 
CREATE PROCEDURE dbo.Enqueue(@absolute_url varchar(255), @depth int, @priorty int, @host varchar(255)) 
AS 
BEGIN 
    INSERT INTO [WebshopCrawler].[dbo].[PriorityQueue] (absolute_url, depth, priorty, domain_host) VALUES (@absolute_url, @depth, @priorty, @host); 
END 
GO 

最優先でアイテムを取得するための手順:

DROP PROCEDURE IF EXISTS dbo.Dequeue 
GO 
CREATE PROCEDURE dbo.Dequeue 
AS 
BEGIN 
    SELECT top 1 absolute_url, depth, priorty 
    FROM [WebshopCrawler].[dbo].[PriorityQueue] 
    WHERE priorty = (SELECT MIN(priorty) FROM [WebshopCrawler].[dbo].[PriorityQueue]) 
END 
GO 

この1つは、より大きなデータで本当に遅くなります。デキューされた項目を削除する

手順:

DROP PROCEDURE IF EXISTS dbo.RemoveFromQueue 
GO 
CREATE PROCEDURE dbo.RemoveFromQueue(@absolute_url varchar(400)) 
AS 
BEGIN 
    DELETE 
    FROM [WebshopCrawler].[dbo].[PriorityQueue] 
    WHERE absolute_url = @absolute_url 
END 
GO 

を私は別のインデックスの多くを使用してみましたが、何も手続きがどの速く行くように見えたん。私は誰かがこれを改善する方法について考えていることを願っています。

答えて

3

Using tables as Queuesをお読みください。重要な問題:

  • デキュー戦略に従ってテーブルを整理する必要があります。 IDENTITYの主キーは絶対に意味をなさない。優先度とデキュー順に基づいたクラスタ化インデックスを使用します。
  • あなたは、単一のステートメントでアトミックデキューだから、これらの線に沿って何かする必要がありますDELETE ... OUTPUT ...

を使用する必要があります。

CREATE TABLE PriorityQueue 
(
    priority int not null, 
    enqueue_time datetime not null default GETUTCDATE(), 
    absolute_url varchar (8000) not null, 
    depth int not null, 
    domain_host varchar (255) not null, 
); 

CREATE CLUSTERED INDEX PriorityQueueCdx on PriorityQueue(priority DESC, enqueue_time); 

CREATE PROCEDURE dbo.Dequeue 
AS 
BEGIN 
    with cte as (
     SELECT top 1 absolute_url, depth, priority 
     FROM [PriorityQueue] with (rowlock, readpast) 
     ORDER BY priority DESC, enqueue_time) 
    DELETE FROM cte 
     OUTPUT DELETED.*; 
END 
GO 
+0

'デフォルトGETUTCDATE()' >>最高むしろその制約に名前を付けますSQL Serverにランダムなものを割り当てるよりも、私はそれがイラストだけであることを知っていますが)人々は盲目的にそれをコピーするかもしれません。 –

+0

第2に、 'enqueue_time'が同じ行が追加された場合、高速挿入やバルク挿入時にソートが保証されません。それは待ち行列の考え方に反するだろう。 –

+0

TT。あなたが正しいです、私は上記を試してみました、それは問題なく、同時にマルチスレッドの原因でURLを挿入することができます。 –