testingMySQL表中是否存在行的最佳方法

我试图找出一个表是否存在一行。 使用MySQL,最好是做这样的查询:

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

并检查总数是否非零或是否更好地执行这样的查询:

 SELECT * FROM table1 WHERE ... LIMIT 1 

并检查是否有行被返回?

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

你也可以尝试使用

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

每个文档

根据以下评论:

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

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

我用TEXT字段进行了一些testing。 考虑到我们有一个1M条目的表。 37个条目等于“某事”:

  • SELECT * FROM test WHERE texte LIKE '%something%' LIMIT 1 with 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%') like SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%') :0.87045907974243s。
  • SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%' LIMIT 1) like = 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 with 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。 (更快)

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

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

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

 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) 

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

以下是如何在一个查询中完成的:

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

我会和COUNT(1)一起去。 它比COUNT(*)更快,因为COUNT(*)testing该行中是否至less有一列是!= NULL。 你不需要,特别是因为你已经有一个条件( WHERE子句)。 COUNT(1)代替testingCOUNT(1)的有效性,这总是有效的,并且花费很less的时间来testing。

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

 SELECT 1 FROM my_table WHERE *indexed_condition* LIMIT 1 

优于:

 SELECT * FROM my_table WHERE *indexed_condition* LIMIT 1 

这是因为第一个查询可以被索引满足,而第二个查询则需要查找行(除非可能所有表中的列都在索引中)。

添加LIMIT子句允许引擎在find任何行后停止。

第一个查询应该可比较:

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

哪个发送相同的信号到引擎。

如果在没有行匹配时需要显式返回,则添加EXISTS包装可能是有意义的。

性能还取决于你的表索引。 有时使用具有适当表索引的旧方法会更好:

 SELECT COUNT(field) FROM table WHERE field = 'something' LIMIT 1 

在“字段”上有一个索引“my_index”

解释将如下所示:

 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE table ref my_index my_index 4 const 1 Using index 

对于非InnoDB表,您还可以使用信息模式表:

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

或者你可以插入原始的sql部分的条件,所以我有'条件'=>数组('Member.id NOT IN(SELECT Membership.member_id FROM memberships AS Membership)')

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

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