SQL 'like'vs '='성능


82

이 질문은 내가 궁금한 점을 둘러싸고 있지만 대답이 정확히 다루지는 않습니다.

것으로 보인다 일반적으로 '='보다 빠른 와일드 카드를 사용하는 경우 '와 같은'입니다. 이것은 일반적인 통념으로 보입니다. 그러나 제한된 수의 다른 고정, 하드 코딩 된 varchar 식별자를 포함하는 열이 있고 그중 하나와 일치하는 모든 행을 선택한다고 가정 해 보겠습니다.

select * from table where value like 'abc%'

select * from table where value = 'abcdefghijklmn'

'좋아요'는 일치 항목을 찾기 위해 처음 세 문자 만 테스트해야하는 반면 '='는 전체 문자열을 비교해야합니다. 이 경우 '좋아요'는 다른 모든 것이 동등하다는 장점이있는 것처럼 보입니다.

이것은 일반적이고 학문적 인 질문을위한 것이므로 어떤 DB를 사용하든 상관 없지만 SQL Server 2005를 사용하여 발생했습니다.


23
당신이 빠뜨린 한 가지 중요한 것은 value인덱싱 여부 입니다. 그렇다면 =테이블 스캔이 필요하지 않은 간단한 조회이며 LIKE당신이 그것에 던지는 모든 진술 에서 바지를 이길 것입니다.
Daniel DiPaolo

7
@Daniel 나는 그것이 틀렸다고 생각합니다. LIKE끝에 와일드 카드가있는 A 는 SARGable이므로 인덱스에서 범위 검색을 수행하며 테이블 스캔이 보이지 않습니다. 이 범위 탐색은 =명령문 과 매우 쉽게 경쟁 할 수 있으며 많은 경우 (만족하는 모든 행이 한 페이지에있는 경우 가능성이없는 조건) 정확히 동일한 성능이되어 동일한 읽기 횟수를 수반 할 수 있습니다.
ErikE

나의 "다른 모든 것이 동등하다"는 것은 "인덱싱 된 여부"문제를 다루기위한 것이지만, 다른 답변에 대한 내 의견에 따라 그 차이가 얼마나 큰지에 대해 적어도 약간의 논쟁이있는 것 같습니다.
MickeyfAgain_BeforeExitOfSO

내 대답을 참조하십시오. 처음에는 인덱싱되지 않은 상태로 테스트했으며 성능은 동일합니다 (두 테이블 스캔 모두 정확히 동일 함). 내 테스트 시나리오에서 색인화 될 것이라고 가정했는데, 그렇지 않으면 왜 성능에 관심이 있습니까?
JNK

5
이 질문에서 '좋아요'에 대한 모든 이야기와 대답은 우리를 여고생처럼 들리게 만듭니다. 마치, 완전히.
JulianR

답변:


64

참조 https://web.archive.org/web/20150209022016/http://myitforum.com/cs2/blogs/jnelson/archive/2007/11/16/108354.aspx를

거기에서 인용 :

LIKE의 인덱스 사용 규칙은 대략 다음과 같습니다.

  • 필터 기준이 =를 사용하고 필드가 인덱싱 된 경우 대부분 INDEX / CLUSTERED INDEX SEEK를 사용합니다.

  • 필터 기준이 와일드 카드없이 LIKE를 사용하는 경우 (예 : 웹 보고서에 %가있을 수 있지만 대신 전체 문자열을 사용하는 매개 변수가있는 경우) 인덱스를 사용할 가능성이 # 1 정도입니다. 증가 된 비용은 거의 아무것도 아닙니다.

  • 필터 기준이 LIKE를 사용하지만 처음에 와일드 카드가있는 경우 (Name0 LIKE '% UTER'에서와 같이) 인덱스를 사용할 가능성이 훨씬 적지 만 여전히 전체 또는 부분 범위에서 INDEX SCAN을 수행 할 수 있습니다. 색인.

  • 그러나 필터 기준이 LIKE를 사용하지만 STRING FIRST로 시작하고 그 이후 어딘가에 와일드 카드가있는 경우 (Name0 LIKE 'COMP % ER'에서와 같이) SQL은 INDEX SEEK를 사용하여 먼저 동일한 행을 빠르게 찾을 수 있습니다. 시작 문자를 입력 한 다음 해당 행에서 정확히 일치하는 항목을 찾습니다.

(또한 SQL 엔진은 쿼리에서 진행되는 다른 작업과 조인하려는 테이블에 따라 예상 한 방식으로 인덱스를 사용하지 않을 수도 있습니다. SQL 엔진은 가장 효율적이고 INDEX SEEK 대신 INDEX SCAN을 포함 할 수있는 방식으로 데이터를 가져 오기 위해 약간 쿼리)


1
링크가 죽었다는
baxx은

2
@baxx 링크 사본은 웨이 백 머신에서 사용할 수 있습니다. web.archive.org/web/20150209022016/http://myitforum.com/cs2/…
alphabet5

45

측정 가능한 차이입니다.

다음을 실행하십시오.

Create Table #TempTester (id int, col1 varchar(20), value varchar(20))
go

INSERT INTO #TempTester (id, col1, value)
VALUES
(1, 'this is #1', 'abcdefghij')
GO

INSERT INTO #TempTester (id, col1, value)
VALUES
(2, 'this is #2', 'foob'),
(3, 'this is #3', 'abdefghic'),
(4, 'this is #4', 'other'),
(5, 'this is #5', 'zyx'),
(6, 'this is #6', 'zyx'),
(7, 'this is #7', 'zyx'),
(8, 'this is #8', 'klm'),
(9, 'this is #9', 'klm'),
(10, 'this is #10', 'zyx')
GO 10000

CREATE CLUSTERED INDEX ixId ON #TempTester(id)CREATE CLUSTERED INDEX ixId ON #TempTester(id)

CREATE NONCLUSTERED INDEX ixTesting ON #TempTester(value)

그때:

SET SHOWPLAN_XML ON

그때:

SELECT * FROM #TempTester WHERE value LIKE 'abc%'

SELECT * FROM #TempTester WHERE value = 'abcdefghij'

결과 실행 계획은 첫 번째 작업 인 LIKE비교의 비용이 비교 보다 약 10 배 더 비싸다는 것을 =보여줍니다.

=비교 를 사용할 수 있다면 그렇게하십시오.


2
실제로 테스트하는 경우 +1. 쇼 플랜을 보는 것만으로도 전체 이야기를 알 수는 없습니다. 나는 내 자신의 테스트를 수행하고 예기치 않은 것을 발견하면 모두에게 알릴 것입니다.
Tom H

1
톰-사실이지만 두 사람이 뒤에서 똑같이 처리되지 않았다는 것을 충분히 알 수있었습니다.
JNK

1
실행 계획에 표시된 비용이 잘못되었습니다. 실제 성능을 반영하지 않습니다. 첫 번째 계획에서는 예상 행 수를 기반으로 19.95하므로 실제로 구현되지 않는 추가 19 개의 키 조회에서 SQL Server 비용이 발생합니다 ( 실제 실행 계획에서도 표시된 비용은 예상 하위 트리 비용을 기반으로 함 )
Martin Smith

약 1M 행이있는 테스트뿐만 아니라 테스트를 수행했으며 두 경우 모두 성능과 쿼리 계획이 동일했습니다. 이 컴퓨터에는 2005가 없으므로 SQL 2008에 있습니다.
Tom H

1
@JNK-방금 시도했습니다-무시할만한 차이가 있지만 차이는 동일합니다. .에 대해 LIKE327ms,. =더 많은 테스트를 실행하고 정확한 평균을 취하면 #temp와 실제 테이블 사이에 실제 차이가 없을 것으로 예상합니다.
Will A

13

또한을 사용할 때 like일부 SQL 버전은 인덱스를 무시하므로 성능이 저하됩니다. 예와 같이 "다음으로 시작"패턴을 사용하지 않는 경우 특히 그렇습니다.

쿼리에 대한 실행 계획을 실제로보고 그것이 무엇을하는지 확인해야하며 가능한 한 적게 추측해야합니다.

즉, "시작"패턴은 SQL Server에서 최적화 될 수 있으며 최적화됩니다. 그것은 것입니다 테이블 인덱스를 사용합니다. EF 4.0로 전환 like을위한 StartsWith바로이 이유.


2
유사 패턴이 쿼리의 일부이고 와일드 카드가 후행 될 때 솔트 가치가있는 관계형 데이터베이스는 인덱스를 무시하지 않습니다. 값을 바인딩하고 데이터베이스가 쿼리 준비와 별도로 바인딩을 지원하는 경우 다른 이야기가 될 수 있습니다.
Dave W. Smith

그것은 내 직감도 나에게 말하고 있지만, 이와 관련하여 SQL 서버에 대한 실무 경험이 있기 때문에 구체적으로 집중했습니다.
Blindy

7

경우 value인덱싱되지 않은되며, 테이블 스캔 모두 결과. 이 시나리오의 성능 차이는 무시할 수 있습니다.

value인덱싱 된 경우 Daniel이 그의 의견에서 지적했듯이 =O (log N) 성능 인 인덱스 조회가 발생합니다. 등을 것이다 - 인덱스의 부분 스캔 결과 (가장 가능성이 얼마나 선택에 따라) >= 'abc'하고 < 'abd'있는가보다 더 많은 노력이 필요합니다 =.

여기서는 SQL Server에 대해 이야기하고 있습니다. 모든 DBMS가 LIKE에 적합하지는 않습니다.


이진 검색이 어떻게 작동하는지 모를 것 같습니다. 두 =경우 like '...%'모두 비교 관계를 기반으로 하위 트리가 선택되기 때문에 sql이 패턴을 인식하고 인식 하는 경우 케이스와 케이스 모두 동일하게 작동합니다.
Blindy

아, 그래. LIKE는 선택성이 충분히 높으면 여전히 O (log N) 일지라도 더 나빠질 가능성이 높습니다.-O (log N)는 부분 스캔을 시작할 위치를 알아 낸 다음 인덱스를 통해 앞으로 여러 번 읽습니다. 끝점 'abd'에 도달합니다.
Will A

예, 그러나 OP의 예에서는 해당 범위에 하나의 값만 있다고 가정하므로이를 염두에두고 비교는 동일합니다.
Blindy

유효한 점-이것이 OP가 말한 것인지 완전히 명확하지는 않지만 그렇지 않은 경우보다 더 가능성이 있다고 생각합니다. 이 경우 성능은 거의 동일합니다.
Will A

LIKE의 범위 탐색은 = 문과 매우 쉽게 경쟁 할 수 있으며, 많은 경우 (만족하는 모든 행이 한 페이지에있는 경우 가능성이없는 조건과 같이) 정확히 동일한 성능이되어 동일한 읽기 횟수를 수반 할 수 있습니다. . "더 많은 노력이 필요할 것"이라는 말은 잘못된 포괄적 인 진술이라고 생각합니다.
ErikE

5

당신은 잘못된 질문을하고 있습니다. 데이터베이스에 문제가 항상이다 운영자 성능하지 SARGability 식의, 그리고 coverability 전체 쿼리. 운영자 자체의 성능은 거의 관련이 없습니다.

그럼, 어떻게 할 LIKE=SARGability의 측면에서 비교? LIKE, 상수로 시작하지 않는 표현식과 함께 사용되는 경우 (예 : 사용될 때 LIKE '%something') 정의상 비 SARGabale입니다. 그러나 그것은 만들 =거나 LIKE 'something%'SARGable합니까? 아니요. SQL 성능에 대한 모든 질문과 마찬가지로 대답은 텍스트 쿼리가 아니라 배포 된 스키마에 있습니다. 이러한 표현식 이를 충족하는 인덱스가 있는 경우 SARGable 있습니다 .

그래서, 진실 사이의 작은 차이가, 말 할 수 =및이 LIKE. 그러나 SQL에서 한 연산자 또는 다른 연산자가 '더 빠르다'고 묻는 것은 '빨리가는 것은 무엇입니까, 빨간 차 또는 파란 차?'와 같습니다. 색상이 아니라 엔진 크기와 차량 무게에 대해 질문해야합니다. 관계형 테이블 최적화에 대한 질문에 접근하려면 WHERE 절 (및 기타 절 )의 인덱스표현식 을 살펴 봐야합니다. WHERE로 시작).


5

mysql 5.5를 사용한 개인적인 예 : 2 개의 테이블, 3 백만 행 중 하나와 10,000 행 중 하나 사이에 내부 조인이있었습니다.

아래와 같이 인덱스에 like를 사용할 때 (와일드 카드 없음) 약 30 초가 소요되었습니다.

where login like '12345678'

'설명'을 사용하면 다음을 얻습니다.

여기에 이미지 설명 입력

동일한 쿼리에 '='를 사용하면 약 0.1 초가 걸립니다.

where login ='600009'

'설명'을 사용하면 다음을 얻습니다.

여기에 이미지 설명 입력

보시다시피 like인덱스 탐색 이 완전히 취소되었으므로 쿼리에 300 배 더 많은 시간이 소요되었습니다.


이를 확인하기 위해 실행 계획을 살펴볼 수도 있습니다.
LittleBobbyTables-Au Revoir

감사합니다 @LittleBobbyTables. 그것을 살펴볼 것입니다.
Aris

최근 버전 (5.7) 때문인지는 모르겠지만 LIKE는 여기서 내 고유 색인을 깨지 않습니다.
Sebas

0

전체 텍스트 검색을 찾고 계실 것 입니다.

전체 텍스트 검색과 달리 LIKE Transact-SQL 조건자는 문자 패턴에서만 작동합니다. 또한 LIKE 술어를 사용하여 형식화 된 2 진 데이터를 쿼리 할 수 ​​없습니다. 또한 많은 양의 구조화되지 않은 텍스트 데이터에 대한 LIKE 쿼리는 동일한 데이터에 대한 동등한 전체 텍스트 쿼리보다 훨씬 느립니다 . 수백만 행의 텍스트 데이터에 대한 LIKE 쿼리는 반환하는 데 몇 분이 걸릴 수 있습니다. 반면 전체 텍스트 쿼리는 반환되는 행 수에 따라 동일한 데이터에 대해 몇 초 이하 만 소요될 수 있습니다.


-1

먼저 첫 번째 것들 ,

그들은 항상 같지는 않다

    select 'Hello' from dual where 'Hello  ' like 'Hello';

    select 'Hello' from dual where 'Hello  ' =  'Hello';

상황이 항상 같지 않을 때 성능에 대해 이야기하는 것은 그다지 적절하지 않습니다.

문자열과 char 변수 만 작업하는 경우 성능에 대해 이야기 할 수 있습니다. 그러나 like 및 "="를 일반적으로 상호 교환 할 수있는 것으로 사용하지 마십시오.

많은 게시물 (위 및 기타 질문)에서 보셨 듯이 동일한 경우 패턴 일치 (콜 레이션)로 인해 유사한 성능이 느려집니다.


경우 'Hello 'A는 VARCHAR(기본값) 당신이 올바른지,하지만이 있다면 CHAR당신은하지 않습니다. a로 캐스트 CHAR(7)하고 둘 다 true를 반환합니다. 또한 TRIMvarchar를 사용 하지 않는 곳에서 도대체 무엇을하고 있습니까? (참고 : 최소한에서 해당되는 경우 SQL Server 2008r2)
abluejelly
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.