2009-09-08 1 views
1

큰 MySQL InnoDB 테이블 (약 1 milion 레코드, 매주 300K 증가)을 블로그 게시물과 함께 보겠습니다. 이 테이블에는 색인이있는 URL 필드가 있습니다.WHERE에 대한 URL 대신 MD5 (URL)를 사용합니다.

새 레코드를 추가하면 같은 URL을 가진 기존 레코드를 확인하고 있습니다.

SELECT COUNT(*) FROM `tablename` WHERE url='http://www.google.com/'; 

현재 시스템은 초당 약 10 ~ 20 쿼리를 생성하고이 금액이 증가 될 것이다 : 여기에 같은 쿼리 모습입니다. URL의 MD5 해시 인 추가 필드를 추가하여 성능을 향상시킬 생각입니다.

SELECT COUNT(*) FROM `tablename` WHERE md5url=MD5('http://www.google.com/'); 

URL 필드에 비해 색인 길이가 더 짧고 일정한 길이로 표시됩니다. 너희들은 그것에 대해 어떻게 생각하니? 그것은 의미가 있습니까?

내 친구의 또 다른 제안은 MD5 대신에 CRC32를 사용하는 것이지만, CRC32의 결과가 얼마나 독특한 지 확신 할 수 없습니다. 이 역할에 대해 CRC32에 관해 어떻게 생각하는지 알려주십시오.

업데이트 : URL 열은 각 행마다 고유합니다.

답변

4

URL에 클러스터되지 않은 색인을 만듭니다. 그러면 SQL 엔진이 내부적으로 모든 최적화 작업을 수행하고 최상의 결과를 얻을 수 있습니다!

VARCHAR 열에 인덱스를 만들면 SQL은 내부적으로 해시를 생성하며 인덱스를 사용하면 더 큰 성능을 제공 할 수 있습니다. 경향은 대한 경우

IF NOT EXISTS(SELECT * FROM `tablename` WHERE url='') 
    -- return TRUE or do your logic here 
+1

"클러스터되지 않은"SQL Server 용어라고 생각했습니다. 단지 인덱스로만 읽으면 안됩니까? –

+0

클러스터되지 않은 인덱스는 데이터의 "가상"인덱스이지만 클러스터 된 인덱스는 데이터의 실제 인덱스입니다. 테이블 당 클러스터 된 인덱스는 하나만 가질 수 있지만 동일한 테이블에 클러스터되지 않은 인덱스가 여러 개있을 수 있습니다. –

+0

NC 인덱스는 MD5 또는 다른 해시를 추가하는 것과 동일하거나 유사한 성능을 얻습니다. url 당 tablename 레코드의 비율이 높으면 두 테이블 구조를 고려할 것입니다.이 테이블 구조에서는 tblUrls 및 tablename에 고유 URL 만 유지되고 해당 키만 저장됩니다. 이렇게하면 삽입 성능이 약간 향상되지만 저장 요구 사항이 줄어들 수 있고 기본 응용 프로그램에 따라 몇 가지 다른 이점이 있습니다. – mjv

0

CRC32가 더 짧고 더 많은 SQL 공간을 절약하기 때문에 CRC32가 실제로이 역할에 더 좋을 것이라고 생각합니다. 많은 쿼리를받는다면 개체는 공간을 절약하는 것입니다. 그것이 일을한다면, 나는 그것을 위해 간다고 말할 것입니다.

비록 32 비트이고 길이가 더 짧기 때문에 물론 MD5만큼 독특하지는 않습니다. 고유 한 것인지 또는 공간을 절약 할 것인지 결정해야합니다.

여전히 CRC32를 선택한다고 생각합니다.

내 시스템은 초당 약 4k 개의 쿼리를 생성하며 링크에 CRC32를 사용합니다.

+0

항상 전체 URL을 별도의 열에 저장하고 MySQL에 동일한 CRC32와 동일한 전체 URL을 비교하도록 요청할 수 있습니다. –

+0

감사합니다. : P – Homework

-1

: 당신은 단지 URL이 있는지 여부를 확인하는 경우

또한, 뭔가 염두에두고, 특정 SQL 제품은이 같은 쿼리와 함께 빠른 결과를 얻을 수 있다는 것입니다 그 select 서술의 결과가 오히려 높기 때문에 다른 해결책은 수를 추적하는 별도의 표를 갖는 것입니다. 분명히 그 기술을 사용하는 것에 대한 높은 벌칙이 있지만,이 특정 쿼리가 일반적인 것이고 너무 느린 경우 이것은 해결책이 될 수 있습니다.

이 솔루션에는 명백한 절충점이 있으며 삽입 된 새 레코드를 개별적으로 삽입 한 후에이 두 번째 테이블을 업데이트하지 않으려는 경우 삽입 속도가 느려질 수 있습니다.

0

빌드에서 색인을 사용하면 항상 최선의, 또는 당신은 어쨌든 자신의 코드베이스에 추가 할 자원 봉사한다)

해시를 사용하여 해시와 URL에 2 열 인덱스를 만듭니다.색인에서 처음 몇 글자 만 선택하면 여전히 완전한 일치를 수행하지만 처음 몇 글자보다 많은 색인을 생성하지는 않습니다. 이 같은

뭔가 :

INDEX(CRC32_col, URL_col(5)) 

어느 해시 그 경우에 작동합니다. 그것은 공간 대 속도의 균형입니다.

또한,이 쿼리는 훨씬 더 빨리 될 것입니다 : 이것은 첫 번째 값을 찾아 중지

SELECT * FROM table WHERE hash_col = 'hashvalue' AND url_col = 'urlvalue' LIMIT 1; 

. COUNT (*) 계산과 일치하는 항목을 훨씬 빠르게 찾아 낼 수 있습니다.

궁극적으로 최선의 선택은 각 변형 및 벤치 마크에 대한 테스트 사례를 만드는 것입니다.

-1

해시를 선택하는 경우 콜리 전을 고려해야합니다. MD5와 같은 큰 해시를 사용하더라도 meet-in-the-middle 확률을 계산해야합니다. 더 잘 알려진 birthday attack입니다. CRC-32와 같은 더 작은 해시의 경우 충돌 확률이 상당히 커질 것이고 WHERE은 해시 전체 URL을 지정해야합니다.

하지만이 질문은 최선의 노력을 기울이는 것이니까? 최적화할만한 것이 있습니까? 이 문제가 이라는 명확한 메트릭과 측정 값이 시스템의 병목 현상 인 인 경우를 제외하고는 조기 최적화를 잘 수행하고있을 수 있습니다. 결국, 이러한 종류의 탐색은 데이터베이스가 모두 최적화 된 것이며, 해시와 같은 작업을 수행하면 실제로 성능이 저하 될 수 있습니다 (예 : 해시가 URL과 다른 분포를 가지므로 조각화 될 수 있음).

0

대부분의 SQL 엔진이 텍스트 열 검색을 위해 내부적으로 해시 함수를 사용하지는 않습니까?

0

해시 키를 사용하고 충돌이 염려되는 경우 두 가지 해시 함수를 사용하고 두 해시 값을 연결하십시오.

하지만 이렇게하더라도 원래 원래 키 값을 행에 저장해야합니다.