我的表中有一个字段有文本数据类型。
以下两个sql查询的性能是否存在差异:
select * from tablename where fieldname="xyz%";
select * from tablename where fieldname="%zyx";
如果我们要实现这些查询的执行,我认为我们需要这样做:
我们必须匹配两个正则表达式(xyz *和* zyx)。
我们必须从头开始检查字符串字符。
对于第一个查询,我们必须读取前三个字符以查看是否存在匹配,但对于第二个字符,我们必须读取,直到我们得到字符串的结尾以确定匹配是否已发生。但是如果我们将字符串的长度存储在某个地方,我们可以直接读取最后三个字符,从而提供与第一种情况类似的性能。
我的问题是,像mysql和oracle这样的商业数据库是否在执行查询时表现出任何差异。
答案 0 :(得分:6)
所有数据库的性能肯定存在差异。 如果列被索引,第一种情况肯定会更快。
我的项目中有类似的实例,用户也可以搜索“以...结尾”(就像你的第二个查询一样)。
由于这是经常使用的操作和查询很慢,
所以你的第二个查询变为:
select * from tablename where fieldname_rev="xyz%";
这种方法与查询开始一样快。
答案 1 :(得分:4)
从你的评论中汲取:“我只是想知道一个匹配的开头是不是来自匹配的两端的差异”。
首先 - 请记住,我们并不是在寻找匹配字符串的最佳算法。我们正在寻找最佳算法来查找一组N行中的所有匹配字符串。我们希望做得比'做算法X,N次'更好。
如果fieldname没有编入索引,那么两个查询之间的性能差别很小 - SQL引擎只会对字符串的前3个或后3个字节进行匹配,这只是一个问题偏移到正确的内存位置。
如果字段名称为IS索引,则两次搜索之间的性能差异很大,因为我们可以丢弃大部分数据,而不是检查所有N行。
即。对于“xyz%”版本,我们可以使用二进制搜索。
我们从中间元素开始,恰好是'彼得'。我们可以立即丢弃'peter'之前的所有内容并在剩余部分中获取中间元素 - 'samantha',依此类推,直到我们找到以'xyz'开头的条目。
对于“%xyz”版本,我们不能这样做,因为任何字符串最终都可能匹配,我们需要查看每个字符串。
随着我们桌子的大小扩大,这两种方法之间的差异变得很大。
为fieldname的反向创建字段/索引的解决方案允许我们再次使用二进制搜索技术。 (在某些数据库中,实际上可以在不创建额外字段的情况下执行此操作,但通过使用特定索引类型,虚拟列等)。
这简化了很多 - 有关数据库索引实际实现的详细信息,请查看B-Tree和B * Tree索引。
答案 2 :(得分:2)
如果fieldname
被编入索引,大多数商业数据库都可以将第一个查询转换为区间搜索
select * from tablename where fieldname>="xyz" and fieldname<"xy{"
非常快。
答案 3 :(得分:1)
是的,以下两个查询之间存在差异:
select * from tablename where fieldname LIKE "xyz%";
select * from tablename where fieldname LIKE "%zyx";
LIKE
fieldname
列上存在索引,“%xyz”可以 不使用索引 - 但“xyz%”可以,这意味着它会更快。在文本中查找子字符串的最快方法是使用全文搜索(FTS) - Oracle和MySQL都有自己的本机功能,还有第三方工具,如Sphinx和Solr。