문제

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. 초기 테이블 스캔을 피하려면 (비교할 값이 인덱스 자체에 포함되어 있기 때문에)
    • 검사 된 값의 범위를 제한합니다.

위의 쿼리의 조건은 없습니다 사기 가능, 이것은 인덱스가 범위 스캔에 사용되지 않습니다 (현재 조건과 함께).

그러나 포인트 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이 "필드"열에서 인덱스를 사용하지 못하게하기에 충분하지 않습니다. 그러나 지수의 전체 스캔이 일어나고있을 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top