web-dev-qa-db-ja.com

MySQLテーブルに行が存在するかどうかをテストするための最良の方法

行がテーブルに存在するかどうか調べようとしています。 MySQLを使用する場合は、次のようにクエリを実行するほうが良いでしょう。

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

そして、合計がゼロ以外であるかどうか、または次のようなクエリを実行するのが良いかどうかを確認します。

SELECT * FROM table1 WHERE ... LIMIT 1

行が返されたかどうかを確認しますか?

どちらのクエリでも、WHERE句はインデックスを使用します。

300
Bernard Chen

あなたも使ってみることができます

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

ドキュメントごと

下のコメントあたり:

SELECT EXISTS(SELECT 1 FROM table1 WHERE ...)
423
Chris Thompson

私は最近この問題についていくつかの研究をしました。それが実装される方法は、そのフィールドがTEXTフィールド、つまり一意でないフィールドである場合は異なる必要があります。

私はTEXTフィールドでいくつかのテストをしました。 1Mエントリのテーブルがあるという事実を考慮してください。 37エントリは「何か」に等しい:

  • 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'と等しいエントリは1つだけです。

  • mysql_num_rows()SELECT * FROM test2 WHERE id ='321321' LIMIT 1: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。 (より速い)
163
Laurent W.

@ 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)
22
jaltek

私の研究では、次のようなスピードで結果が出ています。

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) 
7
shihab mm

コメントの中で触れられていますが、指摘する価値があると思います。

SELECT 1 FROM my_table WHERE *indexed_condition* LIMIT 1

より優れています:

SELECT * FROM my_table WHERE *indexed_condition* LIMIT 1

これは、最初のクエリではインデックスを満たすことができるのに対して、2番目のクエリでは行の検索が必要になるためです(おそらくテーブルのすべての列が使用されるインデックス内にある場合を除く)。

LIMIT節を追加すると、エンジンは行を見つけた後で停止することができます。

最初のクエリは次のようになります。

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

これはエンジンに同じシグナルを送ります(1/*はここで違いはありません)が、私はまだEXISTSを使うとき習慣を強化するために1を書きます:

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

行が一致しない場合に明示的な戻り値が必要な場合は、EXISTSラッピングを追加するのが理にかなっています。

5
Arth

Countは常にdbを使用するための余分な負荷をかけるので、Countを使用しないことをお勧めします。レコードがそこにある場合はSELECT 1を返し、1を返します。扱う。

4
Fatih Karatana

行の自動インクリメントの主キー(id)が存在する場合は取得し、存在しない場合は0を取得すると非常に便利です。

これが単一の問い合わせでどのように行われることができるかです:

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

COUNTクエリは、おそらくそれほど顕著ではありませんが、望みどおりになるまでは高速です。その結果、両方とも十分なはずです。

0
jaywon

私はCOUNT(1)と行きます。 COUNT(*)は、その行の少なくとも1つの列が!= NULLであるかどうかをテストするため、COUNT(*)よりも高速です。特に必要な条件はありません(WHERE節)。代わりにCOUNT(1)1の妥当性をテストします。これは常に有効であり、テストにかかる時間はずっと短くなります。

0
Felix