在使用SQL时,在WHERE
子句中使用=
而不是LIKE
有什么好处
没有任何特殊的运算符,LIKE
和=
是一样的,对吗?
发布于 2010-02-26 03:27:36
不同的运算符
LIKE
和=
是不同的运算符。这里的大多数答案都集中在通配符支持上,这并不是这些运算符之间唯一的区别!
=
是一个对数字和字符串进行操作的比较运算符。比较字符串时,比较运算符会比较整个字符串。
LIKE
是一个字符串运算符,可以逐个字符进行比较。
更复杂的是,两个运算符都使用了对比较结果有重要影响的collation。
鼓舞人心的例子
让我们首先确定一个例子,这些运算符产生明显不同的结果。请允许我引用MySQL手册中的内容:
根据
标准,LIKE在每个字符的基础上执行匹配,因此它可以产生与=比较运算符不同的结果:
mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
+-----------------------------------------+
| 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
+-----------------------------------------+
| 0 |
+-----------------------------------------+
mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
+--------------------------------------+
| 'ä' = 'ae' COLLATE latin1_german2_ci |
+--------------------------------------+
| 1 |
+--------------------------------------+
请注意,MySQL手册的这一页称为字符串比较函数,没有讨论=
,这意味着=
不是严格意义上的字符串比较函数。
=
是如何工作的?
SQL Standard § 8.2描述了=
如何比较字符串:
两个字符串的比较结果如下:
a)如果X的字符长度不等于Y的字符长度,则出于比较的目的,有效地将较短的字符串替换为已经通过在一个或多个填充字符的右侧连接而扩展到较长字符串的长度的自身副本,其中填充字符是基于CS选择的。如果CS具有NO PAD属性,则pad字符是依赖于实现的字符,不同于X和Y字符集中的任何字符,该字符排序少于CS下的任何字符串。否则,填充字符为a。
b) X和Y的比较结果由整理序列CS给出。
c)根据排序顺序,即使两个字符串具有不同的长度或包含不同的字符序列,也可以进行相等的比较。当操作MAX、MIN、DISTINCT、对分组列的引用以及UNION、EXCEPT和INTERSECT运算符引用字符串时,这些操作从一组这样的相等值中选择的特定值取决于实现。
(重点已添加。)
这是什么意思?这意味着在比较字符串时,=
运算符只是当前排序规则的薄薄包装器。排序规则是具有用于比较字符串的各种规则的库。下面是a binary collation from MySQL的一个示例
static int my_strnncoll_binary(const CHARSET_INFO *cs __attribute__((unused)),
const uchar *s, size_t slen,
const uchar *t, size_t tlen,
my_bool t_is_prefix)
{
size_t len= MY_MIN(slen,tlen);
int cmp= memcmp(s,t,len);
return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen);
}
这种特殊的排序规则恰好是逐字节比较的(这就是为什么它被称为“二进制”--它没有赋予字符串任何特殊的含义)。其他排序规则可能提供更高级的比较。
例如,下面是一个支持不区分大小写比较的UTF-8 collation。代码太长了,不能粘贴到这里,但请转到该链接并阅读my_strnncollsp_utf8mb4()
的主体。这种排序规则可以一次处理多个字节,并且可以应用各种转换(例如不区分大小写的比较)。=
运算符完全从排序规则的反复无常中抽象出来。
LIKE
是如何工作的?
SQL Standard § 8.5描述了LIKE
如何比较字符串:
The
M LIKE P
如果存在将M划分为多个子字符串的情况,则为真:
i) M的子串是M的0个或更多个连续的s的序列,并且M的每个子串恰好是一个子串的一部分。
ii)如果P的第i个子串说明符是任意字符说明符,则M的第i个子串是任意单个的。
iii)如果P的第i个子串说明符是任意串说明符,则M的第i个子串是任意0或更多s的序列。
iv)如果P的第i个子串说明符既不是任意字符说明符也不是任意串说明符,则M的第i个子串根据的排序顺序等于该子串说明符,而不是将字符附加到M,并且具有与该子串说明符相同的长度。
v) M的子串的数目等于P的子串说明符的数目。
(重点已添加。)
这是相当冗长的,所以让我们将其分解。第二项和第三项分别指通配符_
和%
。如果P
不包含任何通配符,则只适用项iv。这就是OP所带来的利益问题。
在本例中,它使用当前排序规则将M
中的每个“子字符串”(单个字符)与P
中的每个子字符串进行比较。
结论
底线是,当比较字符串时,=
比较整个字符串,而LIKE
一次比较一个字符。这两种比较都使用当前排序规则。这种差异在某些情况下会导致不同的结果,如本文的第一个示例所示。
你应该使用哪一个?没有人能告诉你这一点--你需要使用适合你的用例的那个。不要过早地通过切换比较运算符来进行优化。
发布于 2009-02-12 22:25:09
等于(=)运算符是“比较运算符比较两个值是否相等”。换句话说,在SQL语句中,除非等式的两边相等,否则不会返回true。例如:
SELECT * FROM Store WHERE Quantity = 200;
LIKE操作符“实现模式匹配比较”,它尝试将“字符串值与包含通配符的模式字符串进行匹配”。例如:
SELECT * FROM Employees WHERE Name LIKE 'Chris%';
LIKE通常只与字符串一起使用,而equals (我相信)会更快。equals运算符将通配符视为原义字符。返回结果的差异如下:
SELECT * FROM Employees WHERE Name = 'Chris';
和
SELECT * FROM Employees WHERE Name LIKE 'Chris';
将返回相同的结果,尽管使用LIKE通常需要更长的时间,因为它的模式匹配。然而,
SELECT * FROM Employees WHERE Name = 'Chris%';
和
SELECT * FROM Employees WHERE Name LIKE 'Chris%';
将返回不同的结果,其中使用"=“只返回带有"Chris%”的结果,而LIKE操作符将返回任何以"Chris“开头的内容。
希望这能有所帮助。可以在here上找到一些有用的信息。
发布于 2015-02-19 23:17:38
这是我对问题SQL 'like' vs '=' performance的另一个答案的复制/粘贴
一个使用MySQL5.5的个人示例:我在两个表之间进行了一个内部连接,一个是300万行,另一个是10000行。
在如下所示的索引上使用like (无通配符)时,大约需要30秒:
where login like '12345678'
使用'explain‘我得到:
当对同一查询使用'=‘时,大约需要0.1秒:
where login ='12345678'
使用'explain‘我得到:
如您所见,like
完全取消了索引查找,因此查询时间增加了300倍。
https://stackoverflow.com/questions/543580
复制相似问题