MySQL의 (비트) 슈퍼 세트 및 서브 세트
-
12-09-2019 - |
문제
MySQL에서 다음 쿼리가 효과적입니다.
SELECT * FROM table WHERE field & number = number;
# to find values with superset of number's bits
SELECT * FROM table WHERE field | number = number;
# to find values with subset of number's bits
... 필드의 색인이 생성 된 경우?
그렇지 않다면 더 빨리 실행할 수있는 방법이 있습니까?
해결책
업데이트:
성능 세부 정보는 내 블로그 에서이 항목을 참조하십시오.
SELECT * FROM table WHERE field & number = number
SELECT * FROM table WHERE field | number = number
이 색인은 두 가지 방식으로 효과적 일 수 있습니다.
- 초기 테이블 스캔을 피하려면 (비교할 값이 인덱스 자체에 포함되어 있기 때문에)
- 검사 된 값의 범위를 제한합니다.
위의 쿼리의 조건은 없습니다 사기 가능, 이것은 인덱스가 범위 스캔에 사용되지 않습니다 (현재 조건과 함께).
그러나 포인트 1
여전히 유지되며 인덱스가 유용 할 수 있습니다.
테이블에 포함 된 경우 100
평균적으로 행당 바이트 1,000,000
레코드, 그러면 테이블 스캔이 스캔해야합니다. 100 Mb
데이터의.
색인이있는 경우 (a 4
-Byte 키, 6
-Byte Row Pointer 및 일부 내부 오버 헤드), 쿼리는 스캔해야합니다. 10 Mb
필터가 성공하면 데이터와 테이블의 추가 데이터.
- 상태가 선택적이지 않으면 테이블 스캔이 더 효율적입니다 (조건과 일치 할 수있는 프로 블리티가 높습니다).
- 상태가 선택적이면 인덱스 스캔이 더 효율적입니다 (조건과 일치 할 수있는 프로블리성이 낮습니다).
이 두 쿼리는 전체 인덱스를 스캔해야합니다.
그러나 다시 작성함으로써 AND
쿼리 인덱스의 범위에서도 혜택을 볼 수 있습니다.
이 조건 :
field & number = number
가장 높은 비트 인 경우에만 필드와 일치 할 수 있습니다. number
세트는 설정됩니다 field
도.
이 추가 조건을 쿼리에 제공해야합니다.
SELECT *
FROM table
WHERE field & number = number
AND field >= 0xFFFFFFFF & ~((2 << FLOOR(LOG(2, 0xFFFFFFFF & ~number))) - 1)
이것은 거친 필터링의 범위와 미세 필터링 조건을 사용합니다.
더 많은 비트 number
결국에는 설정이 없을수록 좋습니다.
다른 팁
나는 옵티마이저가 그 중 하나를 알아낼 것이라고 의심합니다 ...
어쩌면 당신은이 질문에 대해 설명하고 나의 비관적 인 추측을 확인할 수 있습니다. (물론 많은 쿼리 계획 결정은 주어진 데이터베이스의 특정 인스턴스를 기반으로한다는 것을 기억하십시오. 즉, 변수의 데이터 및/ore는 단지 다른 통계 프로파일을 갖는 데이터만을 생성 할 수 있습니다).
테이블에 상당한 양의 행이 있고 "비트 웨이션"기준이 충분히 선택적이라고 가정하면) 모든 단일 행에서 약간의 작동을 피할 때 (또는 조인) 쿼리를 다시 작성하여 가능한 최적화가 달성됩니다. )
그런 것 (개념, 즉 테스트되지 않음)
CREATE TEMPORARY TABLE tblFieldValues
(Field INT);
INSERT INTO tblFieldValues
SELECT DISTINCT Field
FROM table;
-- SELECT * FROM table WHERE field | number = number;
-- now becomes
SELECT *
FROM table t
WHERE field IN
(SELECT Field
FROM tblFieldValues
WHERE field | number = number);
이와 같은 접근 방식의 모든 이점은 다른 사용 사례로 평가되어야합니다 (다른 방법으로 표에 상당한 수의 행을 갖는 모든 것, 그렇지 않으면 직접 "Field | number = number"접근 방식이 충분히 효율적이기 때문입니다). 이것은 훨씬 더 빠를 수 있습니다. "TBLFIELDVALUES"를 매번 재현 할 필요가 없으면 추가 이익을 얻을 수 있습니다. 물론이 테이블의 효율적인 생성은 원래 테이블의 필드의 색인을 의미합니다.
나는 이것을 직접 시도했으며, 비트 동작은 MySQL이 "필드"열에서 인덱스를 사용하지 못하게하기에 충분하지 않습니다. 그러나 지수의 전체 스캔이 일어나고있을 것입니다.