MySQL 테이블에 행이 있는지 테스트하는 가장 좋은 방법


337

테이블에 행이 있는지 확인하려고합니다. MySQL을 사용하면 다음과 같은 쿼리를 수행하는 것이 좋습니다.

SELECT COUNT(*) AS total FROM table1 WHERE ...

합계가 0이 아닌지 또는 다음과 같은 쿼리를 수행하는 것이 더 나은지 확인하십시오.

SELECT * FROM table1 WHERE ... LIMIT 1

행이 반환되었는지 확인하십시오.

두 쿼리에서 WHERE 절은 인덱스를 사용합니다.

답변:


470

당신은 또한 시도 할 수 있습니다 EXISTS:

SELECT EXISTS(SELECT * FROM table1 WHERE ...)

그리고 설명서에 따라 SELECT무엇이든 할 수 있습니다 .

일반적으로 EXISTS 하위 쿼리는 SELECT *로 시작하지만 SELECT 5 또는 SELECT column1 또는 다른 것으로 시작할 수 있습니다. MySQL은 이러한 하위 쿼리에서 SELECT 목록을 무시하므로 아무런 차이가 없습니다.


30
로 테스트하십시오 ...EXISTS( SELECT 1/0 FROM someothertable). SQL Server 및 Oracle의 경우 EXISTS는 일치하는 1 개 이상의 WHERE 기준을 기준으로 부울 만 테스트하므로 *, 1 또는 NULL을 사용하는 데 차이가 없습니다.
OMG Ponies

77
얘들 아, 그것은이 답변에 링크 된 문서에서 2 번 단락 "전통적으로 EXISTS 하위 쿼리는 SELECT *로 시작하지만 SELECT 5 또는 SELECT column1 또는 다른 것으로 시작할 수 있습니다. MySQL은 SELECT 목록을 무시합니다. 하위 쿼리이므로 차이가 없습니다. "
mpen

12
@ChrisThompson : 명령문이 실행될 때 어떻게됩니까? 결과 집합에 무엇이 포함되어 있습니까?
Ashwin

13
@Ashwin에는 0 (존재하지 않음) 또는 1 (존재 함)이 포함됩니다.
fedorqui 'SO 중지 피해'

10
귀하의 검색어가 불필요하다고 생각하고 테스트 했으며이 쿼리가 귀하의 쿼리 SELECT 1 FROM table1 WHERE col = $var LIMIT 1보다 빠릅니다. 그렇다면 쿼리의 장점은 무엇입니까?
Shafizadeh

182

나는 최근에이 주제에 관한 연구를했다. 필드가 고유하지 않은 필드 인 TEXT 필드 인 경우이를 구현하는 방법이 달라야합니다.

TEXT 필드로 몇 가지 테스트를 수행했습니다. 1M 항목이있는 테이블이 있다는 사실을 고려하십시오. 37 개의 항목은 'something'과 같습니다.

  • SELECT * FROM test WHERE texte LIKE '%something%' LIMIT 1mysql_num_rows() : 0.039061069488525s. (빠른)
  • SELECT count(*) as count FROM test WHERE text LIKE '%something% : 16.028197050095s.
  • SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%') : 0.87045907974243s.
  • SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%' LIMIT 1) : 0.044898986816406s.

그러나 이제 BIGINT PK 필드에서 하나의 항목 만 '321321'과 같습니다.

  • SELECT * FROM test2 WHERE id ='321321' LIMIT 1mysql_num_rows() : 0.0089840888977051s.
  • SELECT count(*) as count FROM test2 WHERE id ='321321' : 0.00033879280090332s.
  • SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321') : 0.00023889541625977s.
  • SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321' LIMIT 1): 0.00020313262939453s. (빠른)

2
추가 답변 주셔서 감사합니다. TEXT 필드에 대한 두 가지 가장 빠른 옵션 간의 시간 차이가 꽤 일정하다는 것을 알았습니까? 차이는 크지 않으며 SELECT EXISTS (SELECT 1 ... LIMIT 1)를 사용하는 것이 두 경우 모두에 꽤 좋은 것처럼 보입니다.
Bernard Chen

1
텍스트 필드에 관한 다른 결과와 관련하여 그 차이는 그렇게 중요하지 않습니다. 그럼에도 불구하고 쿼리는 다음을 사용하는 것이 더 나을 것입니다.SELECT 1 FROM test WHERE texte LIKE '%something%' LIMIT 1
Laurent W.

나는 mysql을 시도했고 당신이 사용하는 경우 select 1 ... limit 1, 선택 존재로 둘러싸는 것은 쓸모가 없다
Adrien Horgnies

4
@LittleNooby에는 차이가 있습니다. SELECT EXISTS ...는 true 및 false 값 (1 또는 0)을 제공하고 SELECT 1 ...은 1 또는 비어 있습니다. 상황에 따라 잘못된 값과 빈 세트 사이에는 미묘한 차이가 있습니다.
Quickpick

@LittleNooby는 훌륭한 포인트를 제공하므로 간과하기 쉽습니다. 타이밍에 누락 위의 테스트입니다 SELECT 1 FROM test WHERE ...하지 않고, SELECT EXISTS주위. 아마도 머리카락이 더 빠를 것입니다.
ToolmakerSteve

27

@ChrisThompson의 답변에 대한 간단한 예

예:

mysql> SELECT * FROM table_1;
+----+--------+
| id | col1   |
+----+--------+
|  1 | foo    |
|  2 | bar    |
|  3 | foobar |
+----+--------+
3 rows in set (0.00 sec)

mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 1);
+--------------------------------------------+
| EXISTS(SELECT 1 FROM table_1 WHERE id = 1) |
+--------------------------------------------+
|                                          1 |
+--------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 9);
+--------------------------------------------+
| EXISTS(SELECT 1 FROM table_1 WHERE id = 9) |
+--------------------------------------------+
|                                          0 |
+--------------------------------------------+
1 row in set (0.00 sec)

별명 사용 :

mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 1) AS mycheck;
+---------+
| mycheck |
+---------+
|       1 |
+---------+
1 row in set (0.00 sec)

18

내 연구에서 결과가 다음 속도로 나오는 것을 알 수 있습니다.

select * from table where condition=value
(1 total, Query took 0.0052 sec)

select exists(select * from table where condition=value)
(1 total, Query took 0.0008 sec)

select count(*) from table where condition=value limit 1) 
(1 total, Query took 0.0007 sec)

select exists(select * from table where condition=value limit 1)
(1 total, Query took 0.0006 sec) 

12

의견에서 언급되었지만이 상황에서는 다음과 같이 지적 할 가치가 있다고 생각합니다.

SELECT 1 FROM my_table WHERE *indexed_condition* LIMIT 1

다음보다 우수합니다.

SELECT * FROM my_table WHERE *indexed_condition* LIMIT 1

이는 첫 번째 쿼리가 인덱스에 의해 충족 될 수있는 반면, 두 번째 쿼리는 행 조회가 필요하기 때문입니다 (모든 테이블 열이 사용 된 인덱스에 있지 않는 한).

LIMIT절을 추가하면 행을 찾은 후 엔진이 중지 될 수 있습니다.

첫 번째 쿼리는 다음과 비슷해야합니다.

SELECT EXISTS(SELECT * FROM my_table WHERE *indexed_condition*)

엔진에 동일한 신호를 보내지 만 (1 / *는 여기에 아무런 차이가 없습니다), 나는 여전히 사용할 때 습관을 강화하기 위해 1을 씁니다 EXISTS.

SELECT EXISTS(SELECT 1 FROM my_table WHERE *indexed_condition*)

EXISTS일치하는 행이 없을 때 명시적인 리턴이 필요한 경우 랩핑 을 추가하는 것이 좋습니다.


4

Countcount는 항상 db 사용을 위해 추가로드를 작성 SELECT 1하고 레코드가 널 (null)을 리턴하고 처리 할 수 ​​있으면 1 을 리턴 하므로 사용하지 말 것을 제안 하십시오.


2

COUNT의 아마 눈에 띄게하지만, 지금까지 원하는 결과를 얻는 등, 모두가 충분해야하지만 쿼리는 빠릅니다.


4
그러나 이것은 DB마다 다릅니다. PostgreSQL에서 COUNT (*)가 느린 것으로 알려져 있습니다. PK 열을 선택하고 행을 반환하는지 확인하는 것이 좋습니다.
BalusC 2009

3
(*) COUNT하지만 이노에 느린

2

때때로 id행 의 자동 증가 기본 키 ( )가 존재하고 존재 0하지 않는 경우에는 매우 편리합니다 .

단일 쿼리에서이를 수행하는 방법은 다음과 같습니다.

SELECT IFNULL(`id`, COUNT(*)) FROM WHERE ...

IFNULL(id, 0)대신에 여기를 사용하지 COUNT(*)않습니까?
Ethan Hohensee


-1

나는 함께 갈 것이다 COUNT(1). 그것은보다 빠른입니다 COUNT(*)때문에 COUNT(*)해당 행에서 적어도 하나의 열이! = NULL의 경우 테스트를 참조하십시오. 특히 조건이 이미 있기 때문에 필요하지 않습니다 ( WHERE절). COUNT(1)대신의 유효성을 테스트합니다.의 유효성 1은 항상 유효하며 테스트하는 데 훨씬 적은 시간이 걸립니다.


8
-1 잘못되었습니다. COUNT (*)는 열 값을 보지 않고 행 수만 계산합니다. 여기에 내 대답을 참조하십시오 stackoverflow.com/questions/2876909/...
마크 바이어스

6
COUNT ()는 EXISTS가 처음 행을 찾을 때 리턴 할 수 있으므로 EXISTS보다 훨씬 느립니다.
Will

-1

또는 조건에 원시 SQL 부분을 삽입 할 수 있으므로 'conditions'=> array ( 'Member.id NOT IN (멤버십 AS 멤버쉽으로 멤버십을 선택하십시오)')


-2

COUNT(*) MySQL에서 최적화되었으므로 이전 쿼리가 더 빠를 가능성이 높습니다.


2
MyISAM이 전체 테이블 수를 선택하기 위해 가지고있는 최적화를 참조하고 있습니까? WHERE 조건이 있으면 도움이되지 않았다고 생각했습니다.
Bernard Chen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.