Answers:
您也可以尝试EXISTS
:
SELECT EXISTS(SELECT * FROM table1 WHERE ...)
根据文档,您可以执行SELECT
任何操作。
传统上,EXISTS子查询以SELECT *开头,但可以以SELECT 5或SELECT column1或任何其他形式开头。MySQL会忽略此类子查询中的SELECT列表,因此没有区别。
SELECT 1 FROM table1 WHERE col = $var LIMIT 1
比您的查询更快。那么查询的优势是什么?
我最近对此问题做了一些研究。如果该字段是TEXT字段(非唯一字段),则实现方式必须有所不同。
我用TEXT字段做了一些测试。考虑到我们有一个包含1M条目的表这一事实。37个条目等于“某物”:
SELECT * FROM test WHERE texte LIKE '%something%' LIMIT 1
与
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%')
: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。(快点)SELECT 1 FROM test WHERE texte LIKE '%something%' LIMIT 1
select 1 ... limit 1
,用select包围是没有用的
SELECT 1 FROM test WHERE ...
,没有SELECT EXISTS
它。大概是这样的头发更快。
@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 / *在这里没有区别),但是我仍然会写1以加强使用时的习惯EXISTS
:
SELECT EXISTS(SELECT 1 FROM my_table WHERE *indexed_condition*)
EXISTS
如果在没有行匹配的情况下需要显式返回,则添加包装可能是有意义的。
建议您不要使用,Count
因为count总是会给数据库使用增加负担,如果您的记录在那里SELECT 1
,它将返回1,否则返回null并可以处理。
有时,获取行的自动递增主键(id
)是否存在非常方便0
。
这是在单个查询中可以完成的方法:
SELECT IFNULL(`id`, COUNT(*)) FROM WHERE ...
IFNULL(id, 0)
这里使用而不是COUNT(*)
?
对于非InnoDB表,您还可以使用信息模式表:
我愿意去COUNT(1)
。它比执行测试要快,COUNT(*)
因为要COUNT(*)
进行测试以查看该行中的至少一列是否为!= NULL。您不需要它,尤其是因为您已经有一个条件(该WHERE
子句)。COUNT(1)
而是测试的有效性1
,该有效性始终有效,并且花费更少的时间进行测试。
COUNT(*)
在MySQL中进行了优化,因此一般而言,以前的查询可能会更快。
...EXISTS( SELECT 1/0 FROM someothertable)
。对于SQL Server和Oracle,使用*,1或NULL没什么区别,因为EXISTS仅基于1+的WHERE条件匹配来测试布尔值。