【问题标题】:Difference between performance of the two sql queries?两个sql查询的性能差异?
【发布时间】:2011-03-30 00:36:55
【问题描述】:

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

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

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

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

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

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

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

我的问题是 mysql 和 oracle 等商业数据库在执行查询时的性能是否存在差异。

【问题讨论】:

  • 请问,为什么要匹配这两个正则表达式?
  • 只是我脑海中闪过的一个想法。我认为这是我所说的一个非常普遍的用例。
  • 恰恰相反,这是我们非常不寻常的用户案例。如果需要这两种正则表达式,您可以肯定地说他们的数据库模式是错误的。可能是数据应该分成不同的列。

标签: sql mysql performance oracle string-matching


【解决方案1】:

是的,以下两个查询有区别:

select * from tablename where fieldname LIKE "xyz%";
select * from tablename where fieldname LIKE "%zyx";
  1. 等于 ("=") 运算符不允许在 SQL 中使用通配符 - 您需要使用 LIKE
  2. 查询完全不同
    • “xyz%”将返回以“xyz”开头的记录
    • “%xyz”将返回以“xyz”结尾的记录
  3. 假设fieldname 列上存在索引,“%xyz”可以不使用该索引 - 但“xyz%”可以,这意味着它将是更快。

在文本中查找子字符串的最快方法是使用全文搜索 (FTS) - Oracle 和 MySQL 都有自己的本机功能,还有像 Sphinx 和 Solr 这样的 3rd 方工具。

【讨论】:

    【解决方案2】:

    摘自您的评论:“我只想知道以匹配开头的内容是否与以匹配结尾的内容不同”。

    首先 - 请记住,我们不是在寻找匹配字符串的最佳算法。我们正在寻找在一组 N 行中找到所有匹配字符串的最佳算法。我们希望比“做算法 X,N 次”做得更好。

    如果 fieldname 没有被索引,那么两个查询之间的性能差异将非常小 - SQL 引擎只会对字符串的前 3 个或后 3 个字节进行匹配,这只是一个问题偏移到正确的内存位置。

    如果字段名被索引,两次搜索的性能会有很大差异,因为我们可以丢弃大部分数据,而不是检查所有 N 行。

    即对于“xyz%”版本,我们可以使用二分查找。

    我们从中间元素开始,恰好是“peter”。我们可以立即丢弃 'peter' 之前的所有内容,并获取其余部分的中间元素 - 'samantha',依此类推,直到找到以 'xyz' 开头的条目。

    使用 "%xyz" 版本,我们不能这样做,因为任何字符串都可能在末尾匹配,我们需要查看每个字符串。

    随着我们表的大小扩大,这两种方法之间的差异变得很大。

    为字段名的反向创建字段/索引的解决方案允许我们再次使用二进制搜索技术。 (在某些数据库中,实际上可以在不创建额外字段的情况下执行此操作,但通过使用特定的索引类型、虚拟列等)。

    这被简化了很多 - 有关数据库索引的实际实现的详细信息,请查看 B-Tree 和 B*Tree 索引。

    【讨论】:

      【解决方案3】:

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

      我的项目中有类似的例子,用户也被允许搜索“以”结尾(如您的第二个查询)。

      由于这是经常使用的操作,查询速度慢,

      1. 我们向表中添加了额外的列,该列存储了字段名的反向。
      2. 索引此列
      3. 每当搜索到结尾时,我们 在这个新列中搜索:)(通过反转原始搜索字符串)

      所以你的第二个查询变成:

       select * from tablename where fieldname_rev="xyz%";
      

      这种方法使其与查询开始时一样快。

      【讨论】:

      • @Col。弹片就是我要找的。 @YoK 在理论或数据库手册的任何地方都有记录。你能引用一些这样的来源吗?非常感谢。
      • @iamrohitbanga 我不知道是理论上还是数据库手册?但正如我所说,我是根据我的项目经验写这篇文章的。我会尝试在一些理论中找到它。
      • @iamrohitbanga 大声笑,所以如果没有别人的帮助,你甚至无法说出你在寻找什么?你需要为此努力。确切地知道你想做什么总是有帮助的
      • Hey Col。我之前也提到过,只是YoK在这个问题上有过实践经验。他还重新表述了这个问题。我只是想知道性能是否有任何差异。用例是一般的。我只想知道以匹配开头的是否与以匹配结尾的不同。我觉得如果使用字符串的长度来实现结尾,那么实现应该没有太大的区别。但是,如果您使用词法分析器,它将从头到尾读取字符串。但是dbs呢?他们用什么?
      【解决方案4】:

      如果fieldname被索引,大多数商业数据库可以将第一个查询转换为区间搜索

      select * from tablename where fieldname>="xyz" and fieldname<"xy{"
      

      速度非常快。

      【讨论】:

      • 第二个呢,有没有效果。
      • btw xyz 可以是任何东西。例如,它可能是 '2wssdfj,fsf@sef34'。
      • @iamrohitbanga 这个对话变得越来越抽象。实际上没有人知道你的意思或想要什么。你能在一些现实生活的基础上设计一个例子吗?谢谢
      • 在这种情况下,您的区间搜索将 >= '2wssdfj,fsf@sef34' 和
      猜你喜欢
      • 2021-04-29
      • 1970-01-01
      • 1970-01-01
      • 2016-02-02
      • 1970-01-01
      • 2019-08-06
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      相关资源
      最近更新 更多