测试MySQL表中是否存在行的最佳方法

时间:2009-11-04 20:55:48

标签: sql mysql performance exists

我试图找出表中是否存在行。使用MySQL,最好像这样进行查询:

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

并检查总数是否为非零,或者更好地进行这样的查询:

SELECT * FROM table1 WHERE ... LIMIT 1

并检查是否有任何行返回?

在两个查询中,WHERE子句都使用索引。

12 个答案:

答案 0 :(得分:422)

您也可以尝试使用

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

the documentation

根据以下评论:

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

答案 1 :(得分:163)

我最近对这个问题做了一些研究。如果字段是TEXT字段,非唯一字段,则实现它的方式必须不同。

我已经使用TEXT字段进行了一些测试。考虑到我们有一个包含1M条目的表的事实。 37个条目等于'某事':

  • SELECT * FROM test WHERE texte LIKE '%something%' LIMIT 1 mysql_num_rows():0.039061069488525s。的(FASTER)
  • 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。的(FASTER)

答案 2 :(得分:22)

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

答案 3 :(得分:7)

在我的研究中,我可以发现结果跟随速度。

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) 

答案 4 :(得分:4)

建议你不要使用Count,因为count总是为db使用SELECT 1做额外的加载,如果你的记录在那里它返回 1 ,否则它返回null你可以处理它。

答案 5 :(得分:4)

我觉得值得指出,虽然在评论中提到了,但在这种情况下:

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包装是有意义的。

答案 6 :(得分:2)

有时获取行的自动增量主键(id)非常方便,如果存在,则0如果不存在。

以下是如何在单个查询中完成此操作:

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

答案 7 :(得分:0)

COUNT 查询速度更快,但可能并不明显,但只要获得理想的结果,两者都应该足够了。

答案 8 :(得分:0)

我会选择COUNT(1)。它比COUNT(*)快,因为COUNT(*)测试是否该行中至少有一列是!= NULL。您不需要,尤其是因为您已经有条件(WHERE子句)。 COUNT(1)代之以测试1的有效性,{{1}}始终有效且测试时间更短。

答案 9 :(得分:-1)

对于非InnoDB表,您还可以使用信息架构表:

http://dev.mysql.com/doc/refman/5.1/en/tables-table.html

答案 10 :(得分:-1)

或者您可以将原始sql部分插入条件 所以我有 '条件' =>数组(' Member.id NOT IN(选择Membership.member_id FROM会员资格AS会员资格)')

答案 11 :(得分:-2)

COUNT(*)在MySQL中进行了优化,因此一般来说,前一个查询可能会更快。