2013-09-16 2 views
1

는 어떤 차이가 있습니까 사이 (인덱스 선택 속도?) :는 대 FIND_IN_SET에 어떤 차이가 있습니까 또는

select * from table where x = 'a' or x = 'b' 

select * from table where find_in_set(x, 'a,b') 

내가 하나를 사용해야 그 (것)들의 또는 동등한가? 내 이해에 따르면

+0

사용해보기 설명 좀 봐? 개인적으로 나는 'OR'이 표준 연산이고 함수를 포함하지 않기 때문에 더 빠르다고 생각하지만, MySQL 쿼리 플래너의 추론은 거의 이해하지 못합니다. – Wolph

+0

'하지만 MySQL 쿼리 플래너의 추론을 거의 이해하지 못합니다. 그래서 제가 프로에게 묻습니다! – Markus

답변

-1

,이 값 목록에 대한 값을 검색하고 즉시 일치하는 항목을 찾아로 검색을 생략하기 때문에

select * from table where find_in_set(x, 'a,b') 

빠르게 작동합니다. 그러나 OR은 열의 모든 값에 대해 작동합니다.

내가 틀렸다면 나를 수정하십시오.

1

FIND_IN_SET은 인덱스를 모두 건너 뛰어야하는 함수 호출입니다.

대신

SELECT * FROM `table` WHERE x IN ('a', 'b') 

을 사용하는 것이 좋습니다.

+0

IN의 단점은 준비된 문장으로는 잘 돌아 가지 않는다는 것입니다. Select * From table 여기서 ID IN (?) 작동하지 않습니다. 테이블에서 * FIND_IN_SET (id ,?)를 선택하십시오. – user2782001

+0

사실! 그러나 당신은 아마도 그 사건을 다루기 위해 라이브러리의 확장을 쓸 수 있습니다. –

1

가능하면 언제든지 FIND_IN_SET 을 피해야합니다! 대부분의 경우 열이 정규화되지 않은 경우 (예 : 셀의 CSV)에 사용됩니다. IN은 색인을 사용할 수 있기 때문에 매우 빠릅니다 (색인이있는 경우). 미친 예제는 기본 키를 첫 번째 인수로 사용하여 FIND_IN_SET (primary_index_column, "1,2,3") 을 사용하고 있습니다. with primary_index_column IN (1,2,3) MySQL은 기본 키를 색인으로 사용하고 있습니다. 색인은 매우 빠르며, 문자열 함수는 매우 느립니다. 그 차이는 때때로 1000x입니다.

이 쿼리

left join m1 on (m1.m1id = p1.emxid) WHERE a1.umi=99999 AND p1.adi = 0 AND p1.id IN (13700325,13700273,13692054,13691440,13692237,13691503,13691512,13691621,13691632,13691653,13691659,13691682,13691702,13691705,13691720,13691723,13691728,13691763,13691782,13691786,13691815,13691818,13691826,13691828,13691830,13691906,13691831,13691843,13691846,13691848,13691849,13691860,13691873,13691881,13691893,13691945,13691939,13691942,13691977,13692043,13691995,13691996,13692004,13692006,13692011,13692012,13692033,13692090,13692042,13692055,13692062,13692225,13692072,13692089,13692111,13692122,13692142,13692156,13692167,13692170,13692173,13692176,13692178,13692183,13692187,13692193,13692202,13692208,13692217,13692216,13692236,13692238,13692239,13692260,13692274,13692275,13692276,13692280,13692285,13692289,13692291,13692293,13692299,13692305,13692313,13692338,13692348,13692355,13692356,13692365,13692370,13692372,13692376,13692696,13692707,13692701,13692708,13692715,13692727,13692734,13692733,13692735,13692758,13692761,13692762,13692781,13692851,13692854,13694572,13697874,13697878,13697885,13697891,13697897,13697898,13697903,13697904,13697912,13697914,13699899,13697949,13697971,13697976,13698138,13698775,13699851,13699854,13699858,13699859,13699880,13699905,13699908,13699909,13699918,13699932,13699936,13699950,13699959,13699971,13700298,13700162,13700163,13700174,13700177,13700195,13700201,13700238,13700248,13700267,13700276,13700303,13700393,13700399,13700410) ORDER BY usishow

SELECT DISTINCT 
a1.usi as usishow, 
m1.m1g1 
FROM a1 LEFT JOIN p1 ON (a1.usi = p1.id) 
(M1 및 P1 세 테이블 (A1)을 함유. p1.id가 (P1)의 차 인덱스이다.) 인덱스를 사용하지 FIND_IN_SET(p1.id, 13700325,13700273,...) > 0 사용 상상 결과 14 초에서 (!) 실행 시간. (P1)의 차 인덱스를 사용

p1.id IN (13700325,13700273,...) 

대 0.02 초 (!) 실행 시간을 초래한다. 하나의 값을 포함하는 열 FIND_IN_SET 를 사용

그래서, 테스트 및 EXPLAIN (EXPLAIN SELECT ....) 모든 쿼리! IN (...)과 비교할 때 그럴만 한 가치가 있습니다. 대부분의 경우 시간, 메모리 (디스크 읽기) 및 CPU 전력이 많이 절약됩니다!

관련 문제