2012-01-11 5 views
2

나는 자체 웹 크롤러를 작성하고 있습니다. 현재 나는 uri.absoluteurl과 같은 URL을 직접 저장하고 있습니다. 그래서 내가 그 데이터베이스가 URL이 이미 추가되었는지 아닌지를 쿼리 할 때 데이터베이스에 직접적으로 select pageid from mytable where url='absoluteurl'을 쿼리합니다. 내 코어 내가 7 @ 4.5 ghz의 CPU가 거의 100 % 항상 있기 때문에 이것은 데이터베이스에 추가 스트레스를 일으키는 것 같아요.데이터베이스에 저장된 웹 크롤러 URL - 빠른 URL 조회 - 해싱 - C#

URL에 md5 해시를 데이터베이스에 저장하고 URL이 존재하는지 여부에 따라 조회 속도가 빨라질 수도 있습니다.

이에 대한 아이디어를 기다리고 있습니다. 해당 URL이 데이터베이스에 존재하는지 여부를 확인하기 위해 최선의 방법은 무엇입니까?

# 4.0 C, MS-SQL 2008

예 : http://img62.imageshack.us/img62/589/exampleimage.png

+1

URL 열에 색인이있는 것으로 의심됩니다. –

+0

Eugen Rieck이 이미지를 보시기 바랍니다 : http://img62.imageshack.us/img62/589/exampleimage.png – MonsterMMORPG

+0

이것은 이상하게 보입니다 - 질의 계획은 무시당하는 CPU, 일부 I/O 비용을 보여줍니다. 배고 있다). CPU가 사용자 영역 또는 커널을 사용합니까? –

답변

3

이미 URL 컬럼에 인덱스를 가지고 있기 때문에, 내 생각은 SELECT (페이지 id를 얻을) 다음 존재하지 않는 경우 INSERT는 (새로운 URL)은 CPU를 최고로 만드는 원인입니다. 크롤러에 다중 스레드가있는 경우 tblPages에서 SQL의 동시성/잠금 메커니즘에 과세 할 수 있습니다.

특정 질문에 관해서는 해시 바이트 (md) 대신 CHECKSUM (crc)을 사용합니다. CHECKSUM은 빠르며, VARBINARY가 아닌 INT를 리턴하므로보다 쉽게 ​​색인을 생성 할 수 있습니다.

그러나 CHECKSUM이 INT를 반환하기 때문에 정확하게 충돌이 발생하기 쉽기 때문에 URL을 AND 절로 검색해야합니다.

SELECT PageId FROM tblPages WHERE HashedUrl=CHECKSUM(@url) AND [email protected] 

이제는 (PageUrl이 아닌) HashedUrl에만 열 색인을 넣으십시오. 충돌 가능성 때문에 색인이 고유하지 않아야합니다. 이렇게하면 테이블 행에 도달하기 시작할 때까지 가장 빠른 INSERT 및 SELECT가 제공됩니다.이 경우 INT CHECKSUM 충돌로 인덱싱되지 않은 PageUrl 열에 많은 부분 테이블 검색이 발생합니다. UPDATE

는 여기에 내가

GO 
/* NORMAL METHOD */ 
BEGIN 
SET STATISTICS TIME ON 
-- 
IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE ID = OBJECT_ID(N'tempdb..#Store1')) 
BEGIN 
    DROP TABLE #Store1 
END 
-- Normal 
CREATE TABLE #Store1 (Id INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED, Data VARCHAR(4000)) 
CREATE UNIQUE CLUSTERED INDEX CIX_STORE1_DATA ON #Store1(Data) 
-- Help Create Data 
DECLARE @Data TABLE(Data VARCHAR(4000)) 
INSERT INTO @Data(Data) VALUES ('red.'), ('YELLOW/'), ('green'), ('.BLUE'), ('/violet'), ('PURPLE-'), ('-orange') 
-- The data set we'll use for testing 
INSERT INTO @Data 
    SELECT a.Data + b.Data + c.Data + d.Data + e.Data + f.Data + g.Data 
    FROM @Data a, @Data b, @Data c, @Data d, @Data e, @Data f, @Data g 
-- INSERTION TESTS 
PRINT('INSERT INTO NORMAL') 
INSERT INTO #Store1(Data) 
    SELECT Data FROM @Data 
-- SELECTION TESTS 
PRINT('SELECT FROM NORMAL') 
SELECT TOP 5000 d.Data, (SELECT s.Id FROM #Store1 s WHERE s.Data = d.Data) FROM @Data d 
-- 
SET STATISTICS TIME OFF 
END 
GO 
/* USING YOUR OWN CHECKSUM/HASH */ 
BEGIN 
SET STATISTICS TIME ON 
-- 
IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE ID = OBJECT_ID(N'tempdb..#Store2')) 
BEGIN 
    DROP TABLE #Store2 
END 
-- With Hash 
CREATE TABLE #Store2 (Id INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED, Hsh INT, Data VARCHAR(4000)) 
CREATE CLUSTERED INDEX CIX_STORE2_CRC ON #Store2(Hsh) 
-- Help Create Data 
DECLARE @Data TABLE(Data VARCHAR(4000)) 
INSERT INTO @Data(Data) VALUES ('red.'), ('YELLOW/'), ('green'), ('.BLUE'), ('/violet'), ('PURPLE-'), ('-orange') 
-- The data set we'll use for testing 
INSERT INTO @Data 
    SELECT a.Data + b.Data + c.Data + d.Data + e.Data + f.Data + g.Data 
    FROM @Data a, @Data b, @Data c, @Data d, @Data e, @Data f, @Data g 
-- INSERTION TESTS 
PRINT('INSERT INTO CHECKSUM/HASH') 
INSERT INTO #Store2(Hsh, Data) 
    SELECT CHECKSUM(Data), Data FROM @Data 
-- SELECTION TESTS 
PRINT('SELECT FROM CHECKSUM/HASH') 
SELECT TOP 5000 d.Data, (SELECT s.Id FROM #Store2 s WHERE Hsh = CHECKSUM(d.Data) AND Data = d.Data) FROM @Data d 
-- 
SET STATISTICS TIME OFF 
END 

결과를 사용하는 간단한 벤치 마크 코드 (짧은에서) 나의 방법은 빠른 (+ 30 %)을 달성 경과 "대"= 7339 밀리 경과 시간 "삽입의 시간 = 10318 ms "이지만 느린 (-30 %)"경과 된 시간 = 37 ms "와"경과 된 시간 = 28 ms "를 선택합니다.

또 다른 흥미로운 점은 너비 (HTTP 사양 ~ 4kb에 따라)가 900 바이트 (SQL 2008의 최대 허용 가능한 키 크기)를 초과하므로 "올바르게"URL VARCHAR 필드를 INDEX 할 수 없다는 것입니다. SQL에서는 경고 만 표시하지만 일부 INSERT/UPDATES는 잠재적으로 실패 할 수 있음을 경고합니다.

Warning! The maximum key length is 900 bytes. The index 'CIX_STORE1_DATA' has maximum length of 4000 bytes. For some combination of large values, the insert/update operation will fail. 

가 나는 SQL 전문가가 아니에요 자체, 아마도 내 시험 방법은/가장 정확한 유용하지 않다, 그러나 주제는 '블랙 박스'대 관련되지 재치있는 사용자 엔드 최적화 매우 재미있다 .

+0

나는 이것과 비슷한 것을 최근에 가지고있다. 더 빠른 색인 생성을 위해 내부적으로 해시/체크섬을 사용하는 것과 같은 영리한 일을 할 가능성이있는 URL의 색인이 아닙니까? 나는이 질문을 물었다. http://stackoverflow.com/questions/7954602/creating-a-hashcode-for-use-in-a-database-ie-not-using-gethashcode 대부분의 응답은 "삽입하지 않았다. 해시 코드/체크섬, 데이터베이스가 그것에 대해 걱정하게하십시오. " – Chris

+0

stackoverflow에는 "{x} 걱정할 것"이 많이 있습니다. 저는 우리가 쉽게 해결할 수있는 문제를 해결하기 위해 항상 다른 사람들에게 의존 할 때 혁신의 문제와 미래의 기술을 두려워합니다. 어쨌든 - (실제 정보를 추가하지 않고)이 주석에 작은 두 센트의 가치를 추가하십시오 : 괜찮은 샘플 세트를 사용하여 두 가지 방법으로 테스트 해보십시오. 만약 우리가 해시를 삽입하지 않으면 SQL이 더 빠르다면 GJ Microsoft가 - 그렇지 않다면 GJ MonsterMMORPG는 앱을 더 빨리 얻었고 툴 벨트에 대한 또 다른 트릭을 배웠습니다. –

+0

답변 해 주셔서 감사합니다. 이제는 특정 웹 사이트 만 크롤링하고 있습니다. 따라서 총 URL 수는 1 천만을 초과하지 않는다고 분명히 말할 수 있습니다. 나는 충돌 기회가 10m 중에서 매우 낮을 것으로 생각한다. 그리고 그것은 매우 중요하지 않은 문제이므로 많은 충돌을 수월하게 받아 들일 수 있습니다. – MonsterMMORPG