source

여러 OR에 대해 인덱스를 사용하는 MySQL이지만 IN에 대한 인덱스는 없으며 속도가 매우 느립니다.

gigabyte 2022. 9. 18. 10:14
반응형

여러 OR에 대해 인덱스를 사용하는 MySQL이지만 IN에 대한 인덱스는 없으며 속도가 매우 느립니다.

SQL 쿼리가 눈에 잘 띄도록 변경하느라 바빴습니다.또한 5~10% 빨라질 수도 있다는 말도 들었습니다.

이전 SQL 문은 다음과 같습니다.

* 팀 중에서 Team1='을 선택합니다.Joe Bloggs의 OR Team2='Joe Bloggs의 OR Team3='Joe Bloggs'

로 바꿨습니다.

* 'Joe Bloggs'가 속한 팀(팀1, 팀2, 팀3)에서 선택

새로운 쿼리는 속도가 약 10배 느립니다.원인이 무엇인지를 확인한 결과 인덱스를 사용하지 않는 것을 알 수 있었고 인덱스를 강제로 사용하려고 해도 사용하지 않습니다.

테이블에는 약 120,000개의 행이 있으며, 다른 응용 프로그램이 액세스할 수 없기 때문에 테이블 형식을 변경할 수 없습니다.Team1, Team2, Team3 열은 모두 VARCHAR(45)입니다.

왜 인덱스가 새 쿼리에 사용되지 않고 원래 쿼리에 사용되는지 설명해 주실 수 있나요?저는 많은 페이지를 읽었지만 답을 찾을 수 없었습니다.mysql이 인덱스를 사용하지 않는 것이 더 빠르다고 판단하고 있을 가능성이 있다고 읽었습니다만, IN 쿼리가 거의 10배 느리기 때문에, 이 경우는 그렇지 않습니다.

다중 선택(캐시 없이 1000회 실행) - 12.863906860352 경과(캐시 없이 1000회 실행) - 122.73787903786 경과

시간 내 주셔서 감사합니다.

쿼리에서:

SELECT * FROM teams WHERE 'Joe Bloggs' IN (Team1,Team2,Team3)

여러 열을 문자열 리터럴과 비교(조회)하고 있습니다.이 경우 옵티마이저는 일반적으로 검색 대상에 인덱스를 사용합니다.Joe Bloggs값을 찾으려면 ,IN절을 클릭합니다.그러나 문자열 리터럴에는 인덱스를 넣을 수 없습니다.그래서 모든 것이 역전되었고, 이것이 지수가 도움이 되지 않는 이유입니다.

한편, 첫 번째 질문에서는 다음과 같습니다.

SELECT * FROM teams WHERE Team1='Joe Bloggs' OR Team2='Joe Bloggs' OR Team3='Joe Bloggs'

MySQL은 문자열 리터럴을 가져와 B-트리 인덱스를 사용하여 다양한 컬럼과 대조합니다.이것은, 예상대로 동작해, 보고 있는 대로입니다.

"반전 IN"이 있습니다. 옵티마이저는 다음에 대한 지수만 사용합니다.column in (value1, value2, value3).

그러나 각 3개의 열에 별도의 인덱스가 있는 경우 두 가지 시도보다 훨씬 더 나은 성능을 얻을 수 있는 다른 방법이 있습니다.

SELECT * FROM teams WHERE Team1='Joe Bloggs'
UNION
SELECT * FROM teams WHERE Team2='Joe Bloggs'
UNION
SELECT * FROM teams WHERE Team3='Joe Bloggs'

테이블은 3회 쿼리가 되지만 매번 인덱스가 사용됩니다.

UNION로로 합니다.UNION ALL더 를 내다UNION추가 오버헤드 또는 디프로듀싱이 있습니다).

A: A: 사용FULLTEXT (team1, team2, team3) ★★★★★★★★★★★★★★★★★」MATCH(team1, team2, team3) AGAINST ('+Joe +Briggs' IN BOOLEAN MODE)이 접근방식을 사용할 때는 많은 주의가 필요합니다만, 이 접근방식이 적용되면 매우 빠릅니다.

플랜 B: "테이블 형식을 변경할 수 없습니다"라고 해도, VIEWS로 게임을 실시해, 어레이(팀)를 열로 분할하는 것을 방지할 수 있습니다.

퍼포먼스가 왜 다른지 모르겠어요.어느 경우든 인덱스는 사용되지 않는 것 같습니다.

다음과 같이 쿼리를 작성할 수 있습니다.

SELECT t.*
FROM teams t
WHERE Team1 = 'Joe Bloggs'
UNION ALL
SELECT t.*
FROM teams t
WHERE Team2 = 'Joe Bloggs' AND Team1 <> 'Joe Bloggs' 
UNION ALL
SELECT t.*
FROM teams t
WHERE Team3 =  'Joe Bloggs'
  AND Team2 <> 'Joe Bloggs'
  AND Team1 <> 'Joe Bloggs';

하면 할 수 .(Team1),(Team2, Team1) , , , , 입니다.(Team3, Team2, Team1).

언급URL : https://stackoverflow.com/questions/51540919/mysql-using-indexes-for-multiple-ors-but-no-index-for-in-and-so-much-slower

반응형