Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >为什么MySQL (InnoDB)性能有很大的差异?

为什么MySQL (InnoDB)性能有很大的差异?
EN

Stack Overflow用户
提问于 2012-03-12 12:31:20
回答 3查看 361关注 0票数 1

我开始研究为什么Django管理中的某些搜索非常慢(请参阅这里)。深入研究后,我发现MySQL (5.1,InnoDB表)的性能在不同查询之间有很大差异。例如:

Django生成的这个查询(在4个字段中查找'c‘、'd’和'e‘,两个相关字段)获取89 ms,并返回3093行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT DISTINCT `donnees_artiste`.`id`
    FROM `donnees_artiste`
LEFT OUTER JOIN `donnees_artiste_evenements`
    ON (`donnees_artiste`.`id` = `donnees_artiste_evenements`.`artiste_id`)
LEFT OUTER JOIN `donnees_evenement`
    ON (`donnees_artiste_evenements`.`evenement_id` = `donnees_evenement`.`id`)
LEFT OUTER JOIN `donnees_artiste_evenements` T4
    ON (`donnees_artiste`.`id` = T4.`artiste_id`)
LEFT OUTER JOIN `donnees_evenement` T5
    ON (T4.`evenement_id` = T5.`id`)
LEFT OUTER JOIN `donnees_artiste_evenements` T6
    ON (`donnees_artiste`.`id` = T6.`artiste_id`)
LEFT OUTER JOIN `donnees_evenement` T7
    ON (T6.`evenement_id` = T7.`id`)

WHERE (
    (`donnees_artiste`.`nom` LIKE '%c%'
  OR `donnees_artiste`.`prenom` LIKE '%c%'
  OR `donnees_evenement`.`cote` LIKE '%c%'
  OR `donnees_evenement`.`titre` LIKE '%c%' )
AND (`donnees_artiste`.`nom` LIKE '%d%'
  OR `donnees_artiste`.`prenom` LIKE '%d%'
  OR T5.`cote` LIKE '%d%'
  OR T5.`titre` LIKE '%d%' )
AND (`donnees_artiste`.`nom` LIKE '%e%'
  OR `donnees_artiste`.`prenom` LIKE '%e%'
  OR T7.`cote` LIKE '%e%'
  OR T7.`titre` LIKE '%e%' )
);

如果我用'k‘替换'e’,那么它基本上是相同的查询,它将花费8720 ms (增加100倍)并返回931行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT DISTINCT `donnees_artiste`.`id`
    FROM `donnees_artiste`
LEFT OUTER JOIN `donnees_artiste_evenements`
    ON (`donnees_artiste`.`id` = `donnees_artiste_evenements`.`artiste_id`)
LEFT OUTER JOIN `donnees_evenement`
    ON (`donnees_artiste_evenements`.`evenement_id` = `donnees_evenement`.`id`)
LEFT OUTER JOIN `donnees_artiste_evenements` T4
    ON (`donnees_artiste`.`id` = T4.`artiste_id`)
LEFT OUTER JOIN `donnees_evenement` T5
    ON (T4.`evenement_id` = T5.`id`)
LEFT OUTER JOIN `donnees_artiste_evenements` T6
    ON (`donnees_artiste`.`id` = T6.`artiste_id`)
LEFT OUTER JOIN `donnees_evenement` T7
    ON (T6.`evenement_id` = T7.`id`)

WHERE (
    (`donnees_artiste`.`nom` LIKE '%c%'
  OR `donnees_artiste`.`prenom` LIKE '%c%'
  OR `donnees_evenement`.`cote` LIKE '%c%'
  OR `donnees_evenement`.`titre` LIKE '%c%' )
AND (`donnees_artiste`.`nom` LIKE '%d%'
  OR `donnees_artiste`.`prenom` LIKE '%d%'
  OR T5.`cote` LIKE '%d%'
  OR T5.`titre` LIKE '%d%' )
AND (`donnees_artiste`.`nom` LIKE '%k%'
  OR `donnees_artiste`.`prenom` LIKE '%k%'
  OR T7.`cote` LIKE '%k%'
  OR T7.`titre` LIKE '%k%' )
);

这两个查询都提供了相同的EXPLAIN,因此没有任何线索。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ID  SELECT_TYPE     TABLE   TYPE    POSSIBLE_KEYS   KEY     KEY_LEN     REF     ROWS    EXTRA
1   SIMPLE  donnees_artiste     ALL     None    None    None    None    4368    Using temporary; Using filesort
1   SIMPLE  donnees_artiste_evenements  ref     artiste_id,donnees_artiste_evenements_eb99df11  artiste_id  4   mmac.donnees_artiste.id     1   Using index; Distinct
1   SIMPLE  donnees_evenement   eq_ref  PRIMARY,donnees_evenements_id_index     PRIMARY     4   mmac.donnees_artiste_evenements.evenement_id    1   Using where; Distinct
1   SIMPLE  T4  ref     artiste_id,donnees_artiste_evenements_eb99df11  artiste_id  4   mmac.donnees_artiste.id     1   Using index; Distinct
1   SIMPLE  T5  eq_ref  PRIMARY,donnees_evenements_id_index     PRIMARY     4   mmac.T4.evenement_id    1   Using where; Distinct
1   SIMPLE  T6  ref     artiste_id,donnees_artiste_evenements_eb99df11  artiste_id  4   mmac.donnees_artiste.id     1   Using index; Distinct
1   SIMPLE  T7  eq_ref  PRIMARY,donnees_evenements_id_index     PRIMARY     4   mmac.T6.evenement_id    1   Using where; Distinct

另外,如果我对第一个查询执行COUNT,则需要11200 ms。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT COUNT(DISTINCT `donnees_artiste`.`id`)
    FROM `donnees_artiste`
LEFT OUTER JOIN `donnees_artiste_evenements`
    ON (`donnees_artiste`.`id` = `donnees_artiste_evenements`.`artiste_id`)
LEFT OUTER JOIN `donnees_evenement`
    ON (`donnees_artiste_evenements`.`evenement_id` = `donnees_evenement`.`id`)
LEFT OUTER JOIN `donnees_artiste_evenements` T4
    ON (`donnees_artiste`.`id` = T4.`artiste_id`)
LEFT OUTER JOIN `donnees_evenement` T5
    ON (T4.`evenement_id` = T5.`id`)
LEFT OUTER JOIN `donnees_artiste_evenements` T6
    ON (`donnees_artiste`.`id` = T6.`artiste_id`)
LEFT OUTER JOIN `donnees_evenement` T7
    ON (T6.`evenement_id` = T7.`id`)

WHERE (
    (`donnees_artiste`.`nom` LIKE '%c%'
  OR `donnees_artiste`.`prenom` LIKE '%c%'
  OR `donnees_evenement`.`cote` LIKE '%c%'
  OR `donnees_evenement`.`titre` LIKE '%c%' )
AND (`donnees_artiste`.`nom` LIKE '%d%'
  OR `donnees_artiste`.`prenom` LIKE '%d%'
  OR T5.`cote` LIKE '%d%'
  OR T5.`titre` LIKE '%d%' )
AND (`donnees_artiste`.`nom` LIKE '%e%'
  OR `donnees_artiste`.`prenom` LIKE '%e%'
  OR T7.`cote` LIKE '%e%'
  OR T7.`titre` LIKE '%e%' )
);

我的innodb_buffer_pool_size设置得很高。我在所有相关字段和主键上都有索引,并且我已经优化了我的表。

那么,为什么第一个查询如此快,而其他两个查询却如此缓慢?这3个查询只是例子。很多时候,我只是从查询中更改或删除一个字符,这对查询时间产生了很大影响。但我看不见任何图案。

更新

性能问题肯定来自Django如何生成这些查询。所有这些冗余的LEFT OUTER JOIN链接在一起,扼杀了性能。目前,我还不完全清楚这是Django SQL生成器中的错误,是如何为搜索字段构建查询的bug,还是Django开发人员所期望的那样。我还在调查,但至少在Django的行为中有一件奇怪的事.

如果我运行这个查询(这不一定等同于第二个查询,但不算太远),结果会非常快(161 ms,没有缓存):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT DISTINCT `donnees_artiste`.`id`
    FROM `donnees_artiste`
LEFT OUTER JOIN `donnees_artiste_evenements`
    ON (`donnees_artiste`.`id` = `donnees_artiste_evenements`.`artiste_id`)
LEFT OUTER JOIN `donnees_evenement`
    ON (`donnees_artiste_evenements`.`evenement_id` = `donnees_evenement`.`id`)

WHERE (
    (`donnees_artiste`.`nom` LIKE '%c%'
  OR `donnees_artiste`.`prenom` LIKE '%c%'
  OR `donnees_evenement`.`cote` LIKE '%c%'
  OR `donnees_evenement`.`titre` LIKE '%c%' )
AND (`donnees_artiste`.`nom` LIKE '%d%'
  OR `donnees_artiste`.`prenom` LIKE '%d%'
  OR `donnees_evenement`.`cote` LIKE '%d%'
  OR `donnees_evenement`.`titre` LIKE '%d%' )
AND (`donnees_artiste`.`nom` LIKE '%k%'
  OR `donnees_artiste`.`prenom` LIKE '%k%'
  OR `donnees_evenement`.`cote` LIKE '%k%'
  OR `donnees_evenement`.`titre` LIKE '%k%' )
);

第二次更新

最后,在Django中,这不是一个bug,我很确定这是想要的行为。其思想是,在多项搜索中,下一项的搜索是在上一项的子集返回上完成的,因此,对于相关字段,所有的项都不必在同一行中才能匹配。为此,DB必须创建包含每个子集的临时表并对其进行扫描。这就解释了为什么会有很多变化,因为如果第一个项只匹配几行,那么临时表就会很小,而对后续项的搜索将很快(因为它们将在一个小表上完成)。这两个查询之间的差别是微妙的,但是Django查询通常可以返回更多的匹配。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-12 13:16:32

我认为,答案是,在大多数情况下,e位于扫描字符串的开头,在第一次搜索的字符串中,允许缩短OR条件,而对k的匹配发生在最后的条件和字符串的末尾。而且,由于k的行要少得多,所以应该在没有任何匹配的情况下完整扫描更多的字符串。

票数 2
EN

Stack Overflow用户

发布于 2012-03-12 14:02:10

如果在引导通配符中使用LIKE模式,则查询将不会使索引受益。以这种方式使用LIKE可能效率很低,其执行时间可能会有很大差异。为什么?

  1. LIKE语句后面的算法停止搜索一行,以防遇到匹配。
  2. 在这种情况下(不使用索引),MySQL应用了一些其他增强算法,这些算法在某些情况下可能适用,也可能不适用。

为什么在您的第三个查询中使用COUNT会大大降低它的速度?

我看你在用innoDB。

innoDB不像MyISAM那样读取存储/缓存值中的行数(如果列不是空的话),因为innoDB对“写”比“读取”(与MyISAM相反)更加优化。每次执行“计数innoDB表”时,都要执行全表扫描或全索引扫描。

您的查询不使用任何索引,这可能是最糟糕的情况,因此会发生全表扫描(是的,它听起来很慢)。

我想你可能会对:MySQL指数感兴趣

票数 2
EN

Stack Overflow用户

发布于 2012-03-12 13:06:02

类型的条件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
WHERE column LIKE '%c%'

无法在column上使用索引。因此,必须对这些列进行全面扫描。

您有多个这样的条件,在它们之间使用OR (这可以确保所有这些表都会被扫描)。最后,您(更确切地说: Django是)在返回结果之前添加了可能需要一个最终文件的DISTINCT

我找不到一个解释的巨大差异在性能(100倍)。也许第一个查询是缓存的。您能尝试在查询的末尾添加ORDER NY NULL并对它们进行计时吗?

生成的查询也不是很好的设计,因为它可能以Join结尾。您要将基表连接到多个表,多个表与基表有一对多的关系。这是性能不佳的原因之一,查询计划将有助于澄清这一点。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9674363

复制
相关文章
Web应用程序测试:Web测试的8步指南
本文翻译自:https://www.guru99.com/web-application-testing.html
小锋学长生活大爆炸
2020/08/13
2.6K0
Web应用程序测试:Web测试的8步指南
基于Python的Web应用程序的Web服务器比较
在本文中,我们将讨论三个主要内容:Python,Web服务器,最重要的是两者之间的比较。
用户2188327
2020/07/03
2.1K0
基于Python的Web应用程序的Web服务器比较
基于Flask的Web应用程序插件式结构
        事实上,很多应用程序基于插件式结构开发,可以很方便了扩展软件的功能,并且这些功能完全可以依托于第三方开发者,只要提供好接口和完备文档,比如wordpress、谷歌火狐浏览器等。
py3study
2020/01/20
8390
Webpack单元测试,e2e测试
此篇文章是续 webpack多入口文件、热更新等体验,主要说明单元测试与e2e测试的基本配置以及相关应用。 一、单元测试 实现单元测试框架的搭建、es6语法的应用、以及测试覆盖率的引入。 1. 需要安装的项目: jasmine:单元测试库 karma:测试框架,配置选择phantomjs浏览器 karma-jasmine:操作jasmine的插件 karma-webpack:webpack与karma的连接 mock:用于数据模拟,用'npm install --save-dev mockjs'安装 kar
sam dragon
2018/01/17
2.4K0
基于nGrinder下的web网站性能测试
nGrinder 看名字估计很多人就猜到跟Grinder有关系。nGrinder是韩国一家公司居于Grinder二次开发的一个性能平台。nGrinder具有 开源、易用、高可用、高扩展等特性,在Grinder基础上实现了多测试并行,通过web管理,实现了集群,同时支持Groovy和Jython脚本语言,(官方上说,Groovy的性能会更好),也实现了对目标服务的监控以及插件的扩展,简单实现更多用户虚拟用户并发(官方上说,8G内存的4核cpu机器可以支持高到8000个虚拟用户)
用户6367961
2019/09/29
1.3K0
180多个Web应用程序测试示例测试用例
180多个Web应用程序测试示例测试用例 假设:假设您的应用程序支持以下功能 各种领域的表格 儿童窗户 应用程序与数据库进行交互 各种搜索过滤条件和显示结果 图片上传 发送电子邮件功能 数据导出功能 通用测试方案 1.所有必填字段均应经过验证,并以星号(*)表示。 2.验证错误消息应正确显示在正确的位置。 3.所有错误消息应以相同的CSS样式显示(例如,使用红色) 4.常规确认消息应使用CSS样式而不是错误消息样式(例如,使用绿色)显示 5.工具提示文本应有意义。 6.下拉字段的第一项应为空白或诸如“选择”
用户7466307
2020/06/17
8.3K0
20条Web测试基于实际测试的功能测试点总结
1、功能相关性:删除/增加一项会不会对其他项产生影响,如产品影响,这些影响是否正确(常见的错误是:增加某个数据记录后,如果该记录某个字段值内容过长,可能在查询的时候让数据例表变形)
程序员白楠楠
2021/08/17
1.1K0
E2E 测试容器化实践
在互联网最初之时,没有任何容器化的概念,那么刚开始的时候是怎样开发软件或者是网站的吗?那时就是计算机便是服务器,就是一个简单的静态网页,没有复杂的业务逻辑。
DevOps时代
2018/08/01
1.6K0
E2E 测试容器化实践
Web应用程序安全性测试指南
由于存储在Web应用程序中的数据量巨大,并且Web上的事务数量增加,因此,对Web应用程序进行适当的安全测试正变得越来越重要。
用户7466307
2020/06/17
1.2K0
Newbe.Pct-Web E2E 自动化测试脚手架
本项目为测试工作者提供了一套“简易的 Web E2E 自动化测试脚手架”。测试工作者可以通过该脚手架,实现编写一些简单的 Web E2E 自动化测试。
newbe36524
2020/03/16
6590
如何知道我们的E2E测试覆盖率?
在单元测试中,很容易知道已经覆盖了哪些代码区域。但是我们能及时知道API调用的动态范围吗?我们一直在思考,既然已经编写了许多 E2E 测试用例,但是我们应该继续编写多少剩余测试?
ThoughtWorks
2020/09/25
1.5K0
jenkins(二) 创建和配置基于Mvven的JEE WEB应用程序
一 构建基于Maven模板的任务 二:填写远程代码仓库地址,遇到如下错误
爱明依
2019/03/12
5160
web安全测试_web测试的主要测试内容
Web安全测试就是要提供证据表明,在面对敌意和恶意输入的时候,web系统应用仍然能够充分地满足它的需求
全栈程序员站长
2022/09/29
1.1K0
web安全测试_web测试的主要测试内容
使用Angular CLI进行单元测试和E2E测试
单元测试. angular cli使用karma进行单元测试. 首先执行ng test --help或者ng test -h查看帮助. 执行测试的话就执行ng test即可, 它会执行项目里所有的.s
solenovex
2018/03/29
2.8K0
使用Angular CLI进行单元测试和E2E测试
Windows c++应用程序通用日志组件(组件及测试程序下载)
引言   众所周知,在调试、跟踪和执行应用程序的过程中,程序的日志能为这些工作提供大量有价值的运行信息。因此,程序的日志对应用程序的运行、维护至关重要。   在如何记录程序日志方面,通常有三种选择:   1、采用Log4CXX等公共开源日志组件:这类日志组件的特点是跨平台且功能比较强大,例如可以把日志发往另一台服务器或记录到数据库中等; 另外,可配置性较高,可以通过配置文件或程序代码对日志进行很多个性化设置。但从另外一个角度看,由于这些优点往往也导致了在使用方面的缺点。首先,对于 一般应用程序来说,它们并不
猿人谷
2018/01/17
1.4K0
Windows c++应用程序通用日志组件(组件及测试程序下载)
编写接口请求库单元测试与 E2E 测试的思考
最近在写适配 Mx Space Server 的 JS SDK。因为想写一个正式一点的库,以后真正能派的上用场的,所以写的时候尽量严谨一点。所以单测和 E2E 也是非常重要。
Innei
2021/12/28
1.1K0
你需要了解的前端测试“金字塔”
来自:开源中国社区 链接:www.oschina.net/translate/the-front-end-test-pyramid-rethink-your-testing 原文:https://medium.freecodecamp.org/the-front-end-test-pyramid-rethink-your-testing-3b343c2bca51 如果您正在测试前端应用程序,则应该了解前端测试金字塔。 在本文中,我们将看到前端测试金字塔是什么,以及如何使用它来创建全面的测试套件。 前端测试金
企鹅号小编
2018/01/11
1.7K0
你需要了解的前端测试“金字塔”
10个基于web的JavaScript最优秀的应用程序库和框架
在所有可用于创建web应用程序的语言中,JavaScript可能是最健壮的库和框架选择。事实上,有太多的东西,很难弄清楚该用哪一个,尤其是当你刚刚开始的时候。
程序你好
2018/07/23
2.3K0
基于 Vue 测试套件引入 Mocha + Expect 测试 Vue 组件
在 Vue 框架中编写单元测试的基本流程和学院君之前在 Laravel 框架和 Go-Micro 微服务框架中编写单元测试时一模一样,只是使用的测试框架和语法有所区别罢了,Laravel 中我们使用的测试框架是 PHPUnit,Go-Micro 中我们使用的测试框架是 GoConvey,而在 Vue 框架中,我们将使用 Vue 生态的 Vue 测试套件并引入 Mocha 测试框架进行 BDD 风格的单元测试。
学院君
2023/03/03
1.4K0
基于 Vue 测试套件引入 Mocha + Expect 测试 Vue 组件
点击加载更多

相似问题

如何在MYSQL中获得两个datetimes之间的差异?

50

如何在Server中获得两个日期之间的秒数?

46

如何在javascript中获得两个日期之间的秒数?

20

计算两个XQuery之间的秒数的dateTimes表达式是什么?

12

如何在Oracle中查找两个datetimes之间的差异

12
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文