两个sql查询的性能差异?

时间:2010-08-15 06:35:27

标签: sql mysql performance oracle string-matching

我的表中有一个字段有文本数据类型。

以下两个sql查询的性能是否存在差异:

 select * from tablename where fieldname="xyz%";
 select * from tablename where fieldname="%zyx";

如果我们要实现这些查询的执行,我认为我们需要这样做:

我们必须匹配两个正则表达式(xyz *和* zyx)。

我们必须从头开始检查字符串字符。

对于第一个查询,我们必须读取前三个字符以查看是否存在匹配,但对于第二个字符,我们必须读取,直到我们得到字符串的结尾以确定匹配是否已发生。但是如果我们将字符串的长度存储在某个地方,我们可以直接读取最后三个字符,从而提供与第一种情况类似的性能。

我的问题是,像mysql和oracle这样的商业数据库是否在执行查询时表现出任何差异。

4 个答案:

答案 0 :(得分:6)

所有数据库的性能肯定存在差异。 如果列被索引,第一种情况肯定会更快。

我的项目中有类似的实例,用户也可以搜索“以...结尾”(就像你的第二个查询一样)。

由于这是经常使用的操作和查询很慢,

  1. 我们在存储了fieldname的反向的表中添加了附加列。
  2. 将此列编入索引
  3. 每当搜索结束时,我们 在这个新专栏中搜索:)(通过反转原始搜索字符串)
  4. 所以你的第二个查询变为:

     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";
  1. equals(“=”)运算符在SQL中不允许使用通配符 - 您需要使用LIKE
  2. 查询完全不同
    • “xyz%”将返回 以“xyz”开头的记录
    • “%xyz”将返回 以“xyz”结尾的记录
  3. 假设fieldname列上存在索引,“%xyz”可以 不使用索引 - 但“xyz%”可以,这意味着它会更快。
  4. 在文本中查找子字符串的最快方法是使用全文搜索(FTS) - Oracle和MySQL都有自己的本机功能,还有第三方工具,如Sphinx和Solr。