两个sql查询的性能差异?

Posted

技术标签:

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

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

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

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

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

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

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

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

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

【问题讨论】:

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

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

select * from tablename where fieldname LIKE "xyz%";
select * from tablename where fieldname LIKE "%zyx";
    等于 ("=") 运算符不允许在 SQL 中使用通配符 - 您需要使用 LIKE 查询完全不同 “xyz%”将返回以“xyz”开头的记录 “%xyz”将返回以“xyz”结尾的记录 假设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】:

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

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

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

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

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

 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' 和

以上是关于两个sql查询的性能差异?的主要内容,如果未能解决你的问题,请参考以下文章

SQL - 使用常量值与参数的任何性能差异?

Sql查询以查找两个给定日期之间的视图百分比差异

使用LIKE子句正确格式化sql查询

sql查询计算不同列和相邻行的两个日期之间的差异

SQL 连接与单表:性能差异?

两个相似查询的巨大速度差异(MySQL ORDER 子句)