MySQL에서 SELECT DISTINCT 또는 GROUP BY가 더 빠릅니다.


273

테이블이 있으면

CREATE TABLE users (
  id int(10) unsigned NOT NULL auto_increment,
  name varchar(255) NOT NULL,
  profession varchar(255) NOT NULL,
  employer varchar(255) NOT NULL,
  PRIMARY KEY  (id)
)

그리고 나는 profession필드의 모든 고유 한 값을 얻고 싶습니다 .

SELECT DISTINCT u.profession FROM users u

또는

SELECT u.profession FROM users u GROUP BY u.profession

?


2
질문을하는 것만 큼 빨리 자신을 테스트 할 수 있습니다. 짜증나게, DISTINCT가 GROUP BY를 능가하는 시나리오를 구성하는 것은 거의 불가능합니다. 이는 분명히 GROUP BY의 목적이 아니기 때문에 성가시다. 그러나 GROUP BY는 오해의 소지가있는 결과를 낳을 수 있으므로이를 피하기에 충분한 이유라고 생각합니다.
딸기

다른 답변을 가진 또 다른 사본이 있습니다. MySql-Distinct vs Group By <<< 참조 GROUP BY가 더 낫습니다
kolunar

쿼리를 실행하여 DISTINCT와 GROUP의 시차를 측정하려면 여기를 참조 하십시오 .
kolunar

답변:


258

그것들은 본질적으로 서로 동등합니다 (사실 이것은 일부 데이터베이스가 실제로 구현 DISTINCT되는 방식입니다 ).

그들 중 하나가 빠르면 될 것 DISTINCT입니다. 두 개는 동일하지만 쿼리 최적화 프로그램은 GROUP BY그룹 구성원을 이용하지 않고 키만 사용 한다는 사실을 파악해야하기 때문입니다 . DISTINCT이것을 명시 적으로 지정하므로 약간 둔한 최적화 프로그램으로 벗어날 수 있습니다.

의심스러운 경우 테스트하십시오!


76
DISTINCT는 인덱스가없는 경우에만 정렬됩니다 (정렬되지 않음). 색인이 있고 사용되면 동의어입니다.
Quassnoi

10
의 정의 DISTINCTGROUP BY차이점 DISTINCT은 출력을 정렬 할 필요가 없으며 GROUP BY기본적으로 수행합니다. 그러나, MySQL의에서조차 DISTINCT+는 ORDER BY수도 여전히 빠르게보다 GROUP BYSquareCog에 의해 설명으로 인해 최적화를위한 추가 힌트.
rustyx

1
많은 양의 데이터를 사용하면 DISTINCT가 훨씬 빠릅니다.
Pankaj Wanjari

7
나는 이것을 테스트하고 인덱스 된 열에서 mysql, group by가 상당히 복잡한 쿼리로 구별되는 것보다 약 6 배 느리다는 것을 알았습니다. 이것을 데이터 포인트로 추가하기 만하면됩니다. 약 100k 행. 그래서 그것을 테스트하고 스스로를 참조하십시오.
Lizardx

MySql-Distinct vs Group By <<< 참조 GROUP BY가 더 낫습니다
kolunar

100

에 대한 색인 profession이있는 경우이 두 가지는 동의어입니다.

그렇지 않으면을 사용하십시오 DISTINCT.

GROUP BYMySQL종류 결과. 당신은 할 수 있습니다 :

SELECT u.profession FROM users u GROUP BY u.profession DESC

직업을 DESC순서대로 정렬하십시오 .

DISTINCT임시 테이블을 작성하고이를 중복 저장에 사용합니다. GROUP BY동일하지만 나중에 고유 한 결과를 정렬합니다.

그래서

SELECT DISTINCT u.profession FROM users u

에 색인이 없으면 더 빠릅니다 profession.


6
정렬을 피하기 위해에 추가 ORDER BY NULL할 수 있습니다 GROUP BY.
Ariel

여전히 느린도 널 (null)에 의해 그룹화와
탄 트룽을

@ThanhTrung : 무엇보다 느린가요?
Quassnoi 2016 년

@Quassnoi groupby 분류를 피하더라도 뚜렷한 것보다 느리다
Thanh Trung

참고 : GROUP BY의 주문 한정자는 MySQL 8에서 더 이상 사용되지 않습니다.
Matthew Lenz

18

단일 열의 DISTINCT와 단일 열의 GROUP BY의 경우 위의 모든 대답이 정확합니다. 모든 DB 엔진에는 자체 구현 및 최적화 기능이 있으며, 차이가 거의없는 경우 (대부분의 경우) 특정 서버 및 특정 버전에 대해 테스트해야합니다! 구현이 바뀔 수 있으므로 ...

그러나 쿼리에서 둘 이상의 열을 선택하면 DISTINCT가 본질적으로 다릅니다! 이 경우 하나의 열 대신 모든 행의 모든 ​​열을 비교하기 때문입니다.

따라서 다음과 같은 것이 있다면

// This will NOT return unique by [id], but unique by (id,name)
SELECT DISTINCT id, name FROM some_query_with_joins

// This will select unique by [id].
SELECT id, name FROM some_query_with_joins GROUP BY id

DISTINCT 키워드가 사용자가 지정한 첫 번째 열로 행을 구별한다고 생각하는 것은 일반적인 실수이지만 DISTINCT는 이러한 방식으로 일반적인 키워드입니다.

따라서 모든 경우에 대해 위의 답변을 올바른 것으로 간주하지 않도록주의해야합니다 ... 원하는 모든 것이 최적화하는 것이 혼란스러워지고 잘못된 결과를 얻을 수 있습니다!


3
이 질문 MySQL 관한 것이지만 두 번째 쿼리는 MySQL 에서만 작동한다는 점에 유의해야합니다 . 거의 모든 다른 DBMS는 GROUP BY 연산자를 잘못 사용하므로 두 번째 명령문을 거부합니다.
a_horse_with_no_name

음, "거의"는 문제가되는 정의입니다. :-) 테스트 한 특정 DBMS 에이 명령문에 대한 오류가 생성 되는지 확인하는 것이 훨씬 도움 이됩니다.
daniel.gindi

3
초보자를위한 Postgres, Oracle, Firebird, DB2, SQL Server. MySQL : sqlfiddle.com/#!2/6897c/1 Postgres : sqlfiddle.com/#!12/6897c/1 Oracle : sqlfiddle.com/#!12/6897c/1 SQL Server : sqlfiddle.com/#!6/ 6897c / 1
a_horse_with_no_name

17

가능하면 가장 간단하고 가장 짧게 가십시오. DISTINCT는 원하는 답을 정확히 제공하기 때문에 찾고자하는 것보다 더 많은 것 같습니다!


7

Group by는 결과를 정렬하는 반면 별개는 피하기 때문에 Distinct보다 고가입니다. 그러나 당신이 null 로 구별 순서를 주는 것과 같은 결과를 그룹으로 만들고 싶다면 ..

SELECT DISTINCT u.profession FROM users u

동일하다

SELECT u.profession FROM users u GROUP BY u.profession order by null

동일하다SELECT profession FROM users GROUP BY profession

6

postgres의 경우에 따라 그룹별로 잘 구분되지 않을 수 있습니다 (다른 db에 대해서는 알지 못함).

테스트 된 예 :

postgres=# select count(*) from (select distinct i from g) a;

count 

10001
(1 row)

Time: 1563,109 ms

postgres=# select count(*) from (select i from g group by i) a;

count
10001
(1 row)

Time: 594,481 ms

http://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks_I

그러니 조심해 ... :)


5

쿼리가 정확히 동일하지 않은 것 같습니다. 적어도 MySQL의 경우.

비교:

  1. northwind.products에서 고유 한 제품 이름을 선택하십시오.
  2. 제품 이름으로 northwind.products 그룹에서 제품 이름을 선택하십시오.

두 번째 쿼리는 Extra에서 "Using filesort"를 추가로 제공합니다.


1
그것들은 그들이 얻는 방법에 관한 것이 아니라 그들이 얻는 것에 관해서 동일합니다. 이상적인 옵티마이 저는 동일한 방식으로 실행하지만 MySQL 옵티마이 저는 이상적이지 않습니다. 당신의 증거에 따르면, DISTINCT가 더 빠를 것 같습니다-O (n) 대 O (n * log n).
SquareCog

"filesort 사용"은 본질적으로 나쁜 것입니까?
vava

이 경우 정렬 할 필요가 없으므로 그룹이 필요하기 때문입니다. MySQL은 동일한 항목을 함께 배치 한 다음 정렬 된 파일을 스캔하여 그룹을 가져옵니다. 구별이 필요하기 때문에 단일 테이블 스캔을 수행하는 동안 키를 해시해야합니다.
SquareCog

1
추가 ORDER BY NULL받는 GROUP BY버전 그들은 동일합니다.
Ariel

3

에서 MySQL을 , " Group By"추가 단계를 사용합니다 filesort. 나는 DISTINCT보다 빠르다 GROUP BY는 것을 알고 놀랍습니다.


3

테스트를 거친 후 GROUP BY가 더 빠르다는 결론에 도달했습니다.

FROM SELECT SQL_NO_CACHE opnamegroep_intern telwerken WHERE opnemergroepopnamegroep_intern에 의해 IN (7,8,9,10,11,12,13) 그룹

635 개의 totaal 0.0944 초 Weergave van 레코드 0-29 (635 개의 totaal, 쿼리 duurde 0.0484 초)

telwerken 어디에서 opnemergroep(7,8,9,10,11,12,13) 에서 sql_no_cache 구별 (opnamegroep_intern)을 선택하십시오

635 totaal 0.2117 초 (거의 100 % 느림) Weergave van records 0-29 (635 totaal, query duurde 0.3468 sec)


2

(기능적 메모의 더)

예를 들어 고용 주당 직원 수를 얻으려는 경우와 같이 GROUP BY를 사용해야하는 경우가 있습니다.

SELECT u.employer, COUNT(u.id) AS "total employees" FROM users u GROUP BY u.employer

이러한 시나리오 DISTINCT u.employer에서는 제대로 작동하지 않습니다. 아마도 방법이 있지만 나는 그것을 모른다. (다른 사람이 DISTINCT를 사용하여 쿼리하는 방법을 알고 있다면 메모를 추가하십시오!)


2

다음은 각 쿼리마다 2 개의 서로 다른 경과 시간을 인쇄하는 간단한 방법입니다.

DECLARE @t1 DATETIME;
DECLARE @t2 DATETIME;

SET @t1 = GETDATE();
SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT
SET @t2 = GETDATE();
PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar);

SET @t1 = GETDATE();
SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY
SET @t2 = GETDATE();
PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar);

또는 SET STATISTICS TIME (Transact-SQL)을 시도하십시오.

SET STATISTICS TIME ON;
SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT
SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY
SET STATISTICS TIME OFF;

다음과 같이 각 명령문을 구문 분석, 컴파일 및 실행하는 데 필요한 밀리 초 수만 표시합니다.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 2 ms.

1

이것은 규칙이 아닙니다

각 쿼리마다 .... 별개로 시도한 다음 그룹별로 ... 각 쿼리를 완료하는 시간을 비교하고 더 빠르게 사용하십시오 ....

내 프로젝트에서 때로는 그룹별로 사용하고 다른 사람들은 구별합니다.


0

그룹 함수 (테이블에 숫자 데이터를 추가하려는 경우 합계, 평균 등)를 수행 할 필요가 없으면 SELECT DISTINCT를 사용하십시오. 나는 그것이 더 빠르다고 생각하지만 그것을 보여줄 것이 없다.

어쨌든 속도가 걱정된다면 열에 색인을 만드십시오.


0

SELECT DISTINCT는 항상 GROUP BY와 같거나 빠릅니다. 일부 시스템 (예 : Oracle)에서는 대부분의 쿼리에서 DISTINCT와 동일하도록 최적화 될 수 있습니다. 다른 경우 (예 : SQL Server) 훨씬 빠를 수 있습니다.


0

문제가 허용하는 경우 결과가 발견되는 즉시 (응답을 버퍼링하지 않음) 종료되도록 최적화되어 있으므로 EXISTS로 시도하십시오. 따라서 WHERE 절에 대한 데이터를 정규화하려는 경우

SELECT FROM SOMETHING S WHERE S.ID IN ( SELECT DISTINCT DCR.SOMETHING_ID FROM DIFF_CARDINALITY_RELATIONSHIP DCR ) -- to keep same cardinality

더 빠른 응답은 다음과 같습니다.

SELECT FROM SOMETHING S WHERE EXISTS ( SELECT 1 FROM DIFF_CARDINALITY_RELATIONSHIP DCR WHERE DCR.SOMETHING_ID = S.ID )

이것이 항상 가능하지는 않지만 가능한 경우 더 빠른 응답을 볼 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.