MySQL テーブルに行が存在するかどうかをテストする最良の方法
-
16-09-2019 - |
質問
テーブルに行が存在するかどうかを確認しようとしています。MySQL を使用する場合、次のようなクエリを実行する方がよいでしょうか。
SELECT COUNT(*) AS total FROM table1 WHERE ...
そして、合計がゼロ以外であるかどうか、または次のようなクエリを実行する方がよいかどうかを確認します。
SELECT * FROM table1 WHERE ... LIMIT 1
行が返されたかどうかを確認しますか?
どちらのクエリでも、WHERE 句はインデックスを使用します。
解決
またEXISTS
を試すことができます:
SELECT EXISTS(SELECT * FROM table1 WHERE ...)
とあたりのドキュメント、あなたは何をSELECT
することができます。
伝統的に、SELECT *でサブクエリを開始しEXISTSが、それができました 5 SELECTまたはSELECT column1のか、まったく何も始まります。 のMySQLの それは違いはありませんので、そのようなサブクエリでSELECTリストを無視します。のの
他のヒント
私は最近このテーマについていくつかの研究を行いました。フィールドが TEXT フィールド (一意ではないフィールド) の場合は、実装方法が異なる必要があります。
TEXT フィールドを使用していくつかのテストを作成しました。100 万個のエントリを含むテーブルがあるという事実を考慮します。37 個のエントリが「何か」に相当します。
SELECT * FROM test WHERE texte LIKE '%something%' LIMIT 1
とmysql_num_rows()
:0.039061069488525秒。 (もっと早く)SELECT count(*) as count FROM test WHERE text LIKE '%something%
:16.028197050095秒。SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%')
:0.87045907974243秒。SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%' LIMIT 1)
:0.044898986816406秒。
しかし、BIGINT PK フィールドでは、 '321321' に等しいエントリは 1 つだけです。
SELECT * FROM test2 WHERE id ='321321' LIMIT 1
とmysql_num_rows()
:0.0089840888977051秒。SELECT count(*) as count FROM test2 WHERE id ='321321'
:0.00033879280090332秒。SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321')
:0.00023889541625977秒。SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321' LIMIT 1)
:0.00020313262939453秒。 (もっと早く)
@ 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)
私の研究では、私は結果は以下の速度になっています。
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)
私はそれが、このような状況では、コメントで触れたが、指摘する価値があると感じ
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 / *ここでの違いはありません)エンジンに同じ信号を送信しますが、私はまだEXISTS
を使用するときの習慣を強化するために1を書くと思います:
SELECT EXISTS(SELECT 1 FROM my_table WHERE *indexed_condition*)
これは、行が一致しないときには、明示的なリターンが必要な場合EXISTS
包装を追加しても意味があります。
カウントは常にデシベル使用Count
のために余分な負荷を行い、右があなたの記録はそれ以外の場合はnullを返し、あなたがそれを扱うことができるならば、それはの1 を返すので、あなたがSELECT 1
を使用しないように提案ます。
時にはない場合、それが存在していて、id
場合は、行の自動インクリメントの主キー(0
)を取得するために非常に便利です。
ここでは、これは単一のクエリで行うことができます方法は次のとおりです。
SELECT IFNULL(`id`, COUNT(*)) FROM WHERE ...
私はCOUNT(1)
で行くと思います。 COUNT(*)
テストは、その行の少なくとも1つの列があるかどうかを確認するためにので、それはCOUNT(*)
よりも高速です!= NULL。あなたはすでに(WHERE
句)に条件を持っている、特にので、それを必要としません。 COUNT(1)
ではなく、常に有効であり、テストするためにはるかに少ない時間をとる、1
の妥当性をテストします。
あ カウント クエリの方が高速ですが、顕著ではないかもしれませんが、目的の結果を得る限り、両方で十分です。
非InnoDBのテーブルの場合、あなたはまた、情報スキーマのテーブルを使用することができます:
それとも、条件に生のSQL部分を挿入することができます ので、私は持っています '条件' =>配列( 'Member.id NOT IN()メンバーAS会員FROM Membership.member_idをSELECT')の
COUNT(*)
は、MySQLの中で最適化されています。