2011-09-02 19 views
1

아래 쿼리는 훌륭하지만 느립니다. 약 7500 개의 행이있는 테이블에서 실행하려면 약 30 초가 걸립니다. 어떻게 속도를 낼 수 있을까요?5 개 필드 중 3 개가 공통적으로있는 행을 찾습니다 - 쿼리 속도를 높이는 방법?

목표는 동일한 테이블에서 "거의 중복"행을 찾는 것입니다. 일치하는 5 개의 필드 중 3 개가 있으면 우리는 명중했습니다.

SELECT  
originalTable.id, 
originalTable.lastname, 
originalTable.firstname, 
originalTable.address, 
originalTable.city, 
originalTable.email 

FROM 
address as originalTable, 
address as compareTable 

WHERE 

# do not find the same record 
originalTable.id != compareTable.id and 

# at least 3 out of those 5 should match 
(originalTable.firstname = compareTable.firstname) + 
(originalTable.lastname = compareTable.lastname)  + 
(originalTable.address = compareTable.address and originalTable.address != '')  + 
(originalTable.city = compareTable.city and originalTable.city != '')  + 
(originalTable.email = compareTable.email and originalTable.email != '') 
>= 3 


GROUP BY 
originalTable.id 

ORDER BY 
originalTable.lastname asc, 
originalTable.firstname asc, 
originalTable.city asc 

모든 최적화 힌트를 주셔서 감사합니다.

+0

이 메이크업 감각'originalTable.id! = compareTable.id'을) ... 단지 목적을 미리보기 위해 "등 MatchFirstName, MatchLastName, MatchCity,"모든 열을 얻을? – ajreal

+0

예. 이것 없이는 레코드 200을 레코드 200과 비교하기 때문에 모든 레코드를 찾지 만 ... 오오 ... 궁금해! :) – sprain

+0

내 사랑, 당신은 행의 크기가'7500 x 7499 = 56242500'이라는 잘못된 조건으로 데카르트 제품을 만들려고 할 수 있습니다 ... – ajreal

답변

0

여기서 직교 제품이 필요합니다. 사실입니다. 나는 다음과 같은 해결책을했다 :이 퍼지 중복 행 각 행 ID를 당신은뿐만 아니라 요청 ID를 당신을 줄 것이다

CREATE TABLE address_dups(INDEX (is_duplicate)) ENGINE=MEMORY 
SELECT 
    originalTable.id, 
    compareTable.id, 
(
    (originalTable.firstname = compareTable.firstname) + 
    (originalTable.lastname = compareTable.lastname) + 
    (originalTable.address = compareTable.address and originalTable.address != '') + 
    (originalTable.city = compareTable.city and originalTable.city != '') + 
    (originalTable.email = compareTable.email and originalTable.email != '') 
    >= 3 
) AS is_duplicate 
FROM 
address as originalTable, 
address as compareTable 
WHERE originalTable.id != compareTable.id; 

SELECT * FROM address_dups WHERE is_duplicate = 1; 

.

0

이미 언급 한대로 비교하려면 데카르트가 필요하지만 부분적으로 만 사용해야합니다. 이름과 성 필드 모두에 값이 필요하기 때문에 성, 이름에 대한 색인을 최소한 갖게됩니다. 그런 다음성에 부분적으로 조건에 WHERE 절을 추가하십시오. 처음 2-3자를 말하십시오. 이렇게하면 같은 이름의 접두어와 나머지 접미사에 대해서만 직교가됩니다. "빌 존스"와 "토냐 스미스"를 비교하는 것은 의미가 없습니다. 그러나 "Bill Jones"vs "William Jones"에 대한 공통의 주소, 도시 및/또는 이메일에 관심이있을 수 있습니다. 직교 비교를 위해 다음 이름 부분을 고려하십시오.

(names fictitious for sample) 
ID Last  First 
1 Adams Brian 
2 Adams Marsha 
3 Andrews Jeff 
4 Brown Steve 
5 Johns Dave 
6 Johnson Bill 
7 Johnson William 

모두 당신은 당신의 WHERE 절에 각 성 (姓)의 왼쪽 3 자격을 갖춘 경우 "아담스는"비교 될 것이다. "Andrews"와 "Brown"은 누구와도 비교할 일치가 없습니다. 그런 다음 "Joh"로 시작하는 3은 데카르트 테스트를 거쳤습니다 ...

이제 where 절에 MORE를 추가하십시오 ... ID 열이 있으므로 where도 where 절의 일부인지 확인하십시오 . 두 번째 테이블의 ID가 항상 현재 테이블보다 큽니다. 예 : "Adams"이름을 비교할 때. ID1이 ID2와 중복되었거나 아닌지 (이 경우는 아님)와 비교 되었는 지 이미 알 수 있으므로 역순으로 이동하여 ID2와 ID1을 다시 비교하십시오.

그래서, (7 개) 기록이 샘플은 그래서

1-2 
2-no more to compare against 
3-no more to compare against 
4-no more to compare against 
5-6 
5-7 
6-7 
7-no more to compare against 

의 비교가 발생합니다 (.. 당신은 할 수 다시 보는 근거로 가까운 상대가 ID를 포함하여 같은 최종적인 것 인 무엇인가 심지어

SELECT 
     originalTable.id, 
     originalTable.lastname, 
     originalTable.firstname, 
     originalTable.address, 
     originalTable.city, 
     originalTable.email, 
     compareTable.ID as MatchID 
    FROM 
     address as originalTable, 
     address as compareTable 
    WHERE 
      originalTable.ID < CompareTable.ID 
     AND left(originalTable.LastName, 3) = left(CompareTable.LastName, 3) 
     AND (originalTable.firstname = compareTable.firstname) 
     + (originalTable.lastname = compareTable.lastname) 
     + (originalTable.address = compareTable.address and originalTable.address != '') 
     + (originalTable.city = compareTable.city and originalTable.city != '') 
     + (originalTable.email = compareTable.email and originalTable.email != '') >= 3 
+0

재미있는 소리. 나는 이것을 시도하고 다시 여기에보고 할 것이다. 나가서 사무실에있는 것처럼 잠시만 기다려주세요. – sprain

+0

불행히도 쿼리가 원래 쿼리와 동일한 결과를 반환하지 않습니다. – sprain

+0

@Sprain, 같은 결과가 아니라 ... 어떻게 다릅니 까? 레코드가 적습니까? 그렇습니다. 나는 묘사 된 바와 같이, ID 기반으로 만 비교할 것을 기대합니다. 유일한 추가 기준은 성의 첫 번째 부분을 강요합니다. 항목이 이름, 주소, 도시, 전자 메일로 3 가지 기준으로 복제 된 경우 해당 항목이 나타나지 않습니다.그렇기 때문에 LEFT (, 3) 평등 검사를 제거하고 OriginalTable.ID DRapp

관련 문제