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 1로 mysql_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 1로 mysql_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.