草庐IT

盘点导致sql执行速度慢的几种情况,都是生产环境踩过的坑

程序员拾山 2024-07-17 原文

当我们遇到慢sql,第一反应可能就是去优化我们的sql语句。一些比较复杂的语句如果执行慢可能还能理解,但是有时一些特别简单的查询也会变得卡顿,“查一行”,也会执行得特别慢。今天,我们盘点一下,都有哪些情况会导致sql执行速度慢。

1,数据库本身压力较大

如果数据库本身的性能压力就比较大,资源比较紧张,CPU占用率或者IO利用率很高,这时会导致所有的语句执行起来都比较慢。这种情况下首先要做的应该是提升服务器的配置,然后观察服务器的性能指标是否平稳。

2,表锁冲突

如果遇到一个简单的查询长时间未返回结果,那么大概率是表被锁住了。一般遇到这种情况,都是通过show processlist命令,查看sql语句的状态。

如图所示,id为8的语句正在等待一个MDL锁,我们可以使用kill命令杀掉这个阻塞线程。

另外还可以通过表sys.schema_table_lock_waits查询阻塞的线程id。

3,行锁冲突

mysql> select * from temp where id =3 for update;

当我们访问id=3这条记录时,使用了for update,表示要对这条语句加锁。但是如果此时已经有另一个事务对这条记录加了锁,并且一直持有不释放锁,那么当前语句就会一直阻塞。

通过上图可以看出,第一个语句不提交事务,第二个语句就一直处于等待阻塞状态。

我们执行show processlist,

可以看出确实有一个线程处于阻塞状态。

锁冲突会导致执行效率降低,进而影响到业务,需要我们重点关注。

4,索引未命中

mysql> select * from t where c=50000 limit 1;

如果字段c上面没有索引,那么就只能走主键id顺序扫描,一直扫描到第50000行才能停下来。

给表数据加索引可以快速提升查询性能,一般来说,因为索引失效导致的慢sql可能是我们平常开发过程中经常遇到的。

5,多表join查询

有了索引,并不代表万事大吉。如果一个比较复杂的sql,需要关联很多表进行查询,即使每张表的索引都可以起到作用,但是由于数据量过多,即使都命中索引,扫描的行数仍然是巨大的。这样sql的执行速度仍然会受到很大影响。

一般来说,超过3个表的join就应该尽量避免,将其拆分为多个查询,使用空间换时间也不失为一个好办法。

总结

总的来说,sql执行速度慢会受到很多种情况的影响,比如表锁,行锁。在实际的业务场景中也许会更复杂,但是处理起来的步骤基本大同小异,只要找到问题的根源,知道如何解决,处理起来就可以做到心中有数,游刃有余。

写文不易,朋友们帮忙点点赞和关注吧,多谢。

有关盘点导致sql执行速度慢的几种情况,都是生产环境踩过的坑的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - 默认情况下使选项为 false - 2

    这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

  3. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  4. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  5. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  6. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  7. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  8. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

  9. ruby - 在不使用 RVM 的情况下在 Mac 上卸载和升级 Ruby - 2

    我最近决定从我的系统中卸载RVM。在thispage提出的一些论点说服我:实际上,我的决定是,我根本不想担心Ruby的多个版本。我只想使用1.9.2-p290版本而不用担心其他任何事情。但是,当我在我的Mac上运行ruby--version时,它告诉我我的版本是1.8.7。我四处寻找如何简单地从我的Mac上卸载这个Ruby,但奇怪的是我没有找到任何东西。似乎唯一想卸载Ruby的人运行linux,而使用Mac的每个人都推荐RVM。如何从我的Mac上卸载Ruby1.8.7?我想升级到1.9.2-p290版本,并且我希望我的系统上只有一个版本。 最佳答案

  10. ruby - 检查是否通过 require 执行或导入了 Ruby 程序 - 2

    如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby​​文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否

随机推荐