데이터베이스 2열 논리 OR 인덱스 또는 별도의 '인덱스' 테이블 생성
-
13-12-2019 - |
문제
나는 다음과 같은 테이블을 가지고 있습니다 :
Matches -> match_id, team_a_id , team_b_id, score
이 테이블에는 두 팀(A팀과 B팀) 간의 경기가 기록됩니다.그러나 A팀이 호스트로 플레이할 때도 있고, B팀이 호스트로 플레이할 때도 있습니다.그래서 A팀과 B팀의 전적 경기를 찾아보려고 했을 때.내가 현재 하고 있는 일은
select * from matches where (team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1);
그러한 경우에 더 나은 접근 방식이 있습니까?위 쿼리의 경우 team_a_id와 team_b_id 조합의 인덱스를 포함하는 것이 맞습니까?하지만 그럼에도 불구하고 AB OR BA 사이에는 여전히 논리적 OR 조건이 있습니다.
대안으로, 또 다른 아이디어가 있습니다. 또 다른 테이블이있는 것입니다.
History -> team_hash, match_id
나는 수동으로 team_hash를 구축합니다. hash(a,b) == hash(b,a)
.그러나 이로 인해 삽입 속도가 약간 느려지지만 읽기 속도는 빨라집니다.아니면 정말 더 빨리 읽히나요?
해결책
복합 인덱스가 있다고 가정합니다. {team_a_id, team_b_id}
, DBMS는 두 개의 인덱스 검색(하나는 team_a_id = 1 and team_b_id = 2
그리고 다른 하나는 team_a_id = 2 and team_b_id = 1
), 매우 빠릅니다.나는 당신이 성능이 부족하다고 생각하지 않을 것이라고 기대합니다.
그러나 이러한 인덱스 검색 중 하나를 제거하는 방법이 있습니다.제약 조건 추가...
CHECK(team_a_id < team_b_id)
...그리고 "방향"을 인코딩합니다(예:어떤 팀이 호스트인지)를 필요한 경우 별도의 필드에 입력하세요.이렇게 하면 알잖아요 team_a_id = 2 and team_b_id = 1
절대 사실일 수 없으므로 검색만 하면 됩니다. team_a_id = 1 and team_b_id = 2
.
"대칭" 해싱은 좋은 아이디어이지만 다음과 같습니다.
- 해시의 정확성은 선언적으로 적용할 수 없습니다. 트리거를 통해 또는 애플리케이션 수준에서 적용해야 합니다.
- 중복된 데이터입니다.당신은 유지해야합니다
team_a_id
그리고team_b_id
어쨌든 해싱 충돌을 해결하려면.데이터가 클수록 캐시는 작아집니다. - 실제로 인덱스 수가 늘어날 수 있습니다. 참조 무결성을 효율적으로 적용하려면 인덱스가 필요할 수 있습니다.
team_a_id
그리고team_b_id
실제 SQL 쿼리에는 필요하지 않더라도 마찬가지입니다.캐시에 더 많은 압력을 가하는 것 외에도 모든 추가 인덱스를 유지해야 하므로 INSERT/UPDATE/DELETE 성능이 저하될 수 있습니다.클러스터링을 끌 수 없는 InooDB의 상황은 특히 심각하므로 보조 인덱스는 힙 기반 테이블보다 비용이 더 많이 드는 경향이 있습니다("클러스터링의 단점" 참조). 이 기사).
다른 팁
어디에서
와 같은 Where 절을 만들 수도 있습니다.((team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1))
AND team_a_id IN (1,2) AND team_b_id IN (1,2)
.
team_a_id, team_b_id와 같은 색인을 사용할 수 있습니다.