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

Ber*_*hen 313 mysql sql performance exists

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

SELECT COUNT(*) AS total FROM table1 WHERE ...
Run Code Online (Sandbox Code Playgroud)

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

SELECT * FROM table1 WHERE ... LIMIT 1
Run Code Online (Sandbox Code Playgroud)

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

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

Chr*_*son 443

你也可以尝试使用

SELECT EXISTS(SELECT * FROM table1 WHERE ...)
Run Code Online (Sandbox Code Playgroud)

根据文件

根据以下评论:

SELECT EXISTS(SELECT * FROM table1 WHERE ...)
Run Code Online (Sandbox Code Playgroud)

  • 伙计们,它在链接到本答案第2段的文档中说,"传统上,EXISTS子查询以SELECT*开头,但它可以从SELECT 5或SELECT column1开始或者任何东西.MySQL忽略SELECT列表一个子查询,所以没有区别." (77认同)
  • 用`... EXISTS(SELECT 1/0 from someothertable)测试`.对于SQL Server和Oracle - 使用*,1或NULL没有区别,因为EXISTS仅测试基于WHERE标准匹配的1+的布尔值. (28认同)
  • @Ashwin,它包含0(不存在)还是1(存在). (12认同)
  • @ChrisThompson:执行语句时会发生什么?我的意思是结果集包含什么? (11认同)
  • 我认为你的查询是多余的,我测试过,这个查询`SELECT 1 FROM table1 WHERE col = $ var LIMIT 1`比你的查询更快.那么查询的优势是什么? (10认同)
  • @Shafizadeh EXISTS() 版本的优点是在用作标量子查询时返回 0 而不是 NULL,这样您就可以添加多个这些表达式以从中创建“或”表达式。 (5认同)
  • @Shafizadeh提出了一个很好的观点,很容易被忽视.缺少上面的选项是`SELECT 1 FROM test WHERE ... LIMIT 1`,周围没有`SELECT EXISTS`.可能是那种方式更快的头发. (2认同)
  • 为了避免太长的键,请使用“SELECT EXISTS(SELECT 1 FROM table1 WHERE ...) as 'is_exist'” (2认同)

Lau*_* W. 172

我最近对这个问题进行了一些研究.如果字段是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':

  • 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.(快点)

  • @LittleNooby有区别.SELECT EXISTS ...给出真值和假值(1或0),而SELECT 1 ...给出1或空.根据您的情况,假值和空集之间存在细微差别. (3认同)
  • 感谢您的其他答复。您是否发现TEXT字段的两个最快选项之间的时间差异非常一致?差异似乎并不大,在两种情况下使用SELECT EXISTS(SELECT 1 ... LIMIT 1)似乎都不错。 (2认同)
  • 您使用的是哪个版本的 MySQL?至少在 5.5+ 中,“EXISTS (SELECT ...)”和“EXISTS (SELECT ... LIMIT 1)”之间没有区别。MySQL 足够聪明,可以自己插入这个“LIMIT 1”,因为“EXISTS”就是这样工作的:当至少找到一个结果时,它就会停止。 (2认同)

jal*_*tek 23

@ 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)
Run Code Online (Sandbox Code Playgroud)

使用别名:

mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 1) AS mycheck;
+---------+
| mycheck |
+---------+
|       1 |
+---------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)


小智 11

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

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) 
Run Code Online (Sandbox Code Playgroud)


Art*_*rth 9

我认为值得指出的是,尽管在评论中已经提到了这种情况:

SELECT 1 FROM my_table WHERE *indexed_condition* LIMIT 1
Run Code Online (Sandbox Code Playgroud)

优于:

SELECT * FROM my_table WHERE *indexed_condition* LIMIT 1
Run Code Online (Sandbox Code Playgroud)

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

添加该LIMIT子句可使引擎在找到任何行后停止。

第一个查询应类似于:

SELECT EXISTS(SELECT * FROM my_table WHERE *indexed_condition*)
Run Code Online (Sandbox Code Playgroud)

它向引擎发送相同的信号(1 / *在这里没有区别),但是我仍然会写1来加强使用时的习惯EXISTS

SELECT EXISTS(SELECT 1 FROM my_table WHERE *indexed_condition*)
Run Code Online (Sandbox Code Playgroud)

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


Fat*_*ana 5

建议您不要使用,Count因为 count 总是会为数据库使用带来额外的负载,如果您的记录就在那里SELECT 1,它会返回1,否则它会返回 null 并且您可以处理它。