一个数据库的查询速度很慢,但在他的副本上查询速度很快
Posted
技术标签:
【中文标题】一个数据库的查询速度很慢,但在他的副本上查询速度很快【英文标题】:Slow query at one DB, but fast at his copy 【发布时间】:2018-11-16 13:22:51 【问题描述】:我们有一个 Laravel 应用程序(版本 5.4.18),它连接到 mysql(5.6.38)数据库(总共 30 万行),MyISAM 类型。
而且我们有像Model::with('anothermodel')->paginate(25)
这样的api-response,在某个时候这个查询的执行时间已经达到了18秒,这是非常大的价值。我创建了一个带有实时 laravel 环境副本的沙箱,该环境使用完全相同的数据库(在同一台服务器上)的副本,现在这个 api-response 在 2.5 秒内执行。如果我们尝试将沙箱 laravel 连接到实时数据库,那么 api 执行又是 18 秒。请检查图像。
所以如果我们假设问题出在直播网站的数据库表中,但是如果我们尝试用microtime
测量这个查询,那么它将显示生成这个查询并从数据库中获取数据所需的时间是只需 0.7 秒。
因此,如果我们假设问题出在 API 路由或 Laravel 代码中,但如果我只是将其复制到子目录(作为沙箱)中,则完全相同的代码将毫无问题地执行。
有什么想法吗?
还有一些服务器信息:32gb RAM 的 Linux 服务器上的 php 7.0.29。
【问题讨论】:
您是否在实时和本地服务器上安装了 laravel 调试栏?这个查询在 laravel-debugbar 中的时间是多少?您的实时服务器似乎与查询无关。如果查询将是问题,那么您无法在沙盒环境中实现 2.5 秒。当您加载实时数据时,请注意浏览器控制台的网络选项卡并查看调试栏的输出 还取决于您的域(主机)或路由在实时服务器中的解析速度。我会说午餐新的实时环境并安装应用程序。但首先检查实时服务器的连接性。 是否使用OFFSET
进行分页?那很糟。 mysql.rjweb.org/doc.php/pagination
我想知道这是否与导致延迟的数据库服务器上的负载有关
"那么它将显示生成此查询并从数据库中获取数据所需的时间仅为 0.7 秒" - 那么为什么不分析您的应用程序并找出它在做什么呢17 秒?我们无法为您做到这一点。
【参考方案1】:
您是否尝试在实时数据库上重建索引?
在 MySQL 中,这可以通过 REPAIR <table> QUICK
命令完成(快速修复 - 意味着仅修复索引 - 重建它们)。
(申请前请先备份DB...这个命令几乎没有机会破坏DB,但是...)
一些补充说明:
Mysql 主要使用自平衡 B+ 树作为索引,它们试图尽可能地平坦以提供良好的搜索时间。
但在某些情况下(通常与向 DATETIME 列中的增量数据插入有关,例如带有索引的createdAt
)MySQL B+ 树实现无法处理此类负载。生成的树提供的性能会随着时间(几天、几周)不断下降。必须重建此类索引...
如果这种方法对您有帮助 - 每 x
天重建一次索引(上次每周一次对我有用)
【讨论】:
“通常它与向 DATETIME 列中的增量数据插入有关,例如 createdAt 和索引” - 你有任何来源吗? AFAIK 恰恰相反。 @PaulSpiegel 我知道 mysql 使用自平衡树,但看起来在某些情况下 mysql 不能很好地平衡它......这种方法对我有用几次,所以解决方案得到确认 【参考方案2】:可能有几个问题,一个是重建索引,在此之前已解决并进行备份,
另一个是你正在运行的服务器,我的意思是 Apache 或 nginx。
查看 apache 的运行情况
ps auxf
通过打开服务器状态来监控 apache
apachectl fullstatus
A good read here on Apache performance
【讨论】:
【参考方案3】:我有 3 个解决方案给你:
1) 使用此命令检查、优化和修复表:
mysqlcheck -u root -p --auto-repair --check --optimize --all-databases
2) 如果问题未解决,请使用 Newrelic 等监控应用检查您的查询执行计划
3) 有时它不是关于特定表,而是关于数据库损坏,尝试删除并使用旧数据创建一个新表。 How to recover/recreate mysql's default 'mysql' database
【讨论】:
【参考方案4】:您需要修复数据库。
为什么要压缩和修复数据库
本概述解释了使用压缩和修复数据库命令如何帮助预防和纠正以下有时会影响数据库的问题:文件随着使用而变大和文件损坏。
数据库文件随着使用而增长 当您添加和更新数据并更改其设计时,数据库文件会变得更大。这种增长部分来自新数据,但也有一些来自其他来源:
Access 创建临时的隐藏对象来完成各种任务。 有时,这些临时对象在之后仍保留在您的数据库中 Access 不再需要它们。
当你删除一个数据库对象时,该对象的磁盘空间 占用不会自动回收 - 数据库文件仍然 使用该磁盘空间,即使对象已被删除。
当您的数据库文件被剩余的临时对象和已删除对象填满时,其性能可能会下降。对象的打开速度可能会更慢,查询的运行时间可能比正常情况要长,典型的操作通常似乎需要更长的时间。
参考:
https://support.office.com/en-us/article/Compact-and-repair-a-database-6ee60f16-aed0-40ac-bf22-85fa9f4005b2
【讨论】:
【参考方案5】:没有足够的信息来给出详细的诊断。 就我个人而言,当查询执行缓慢时,我会开始检查服务器上的内存和 CPU 占用情况,htop 是一个很好的工具,以防您无法访问任何其他许可软件进行服务器监控,以确保不仅机器是平等的,但工作量也是一样的。 很多时候,此类问题取决于锁定或资源争用,而不是特定查询。 最终隔离一个 sql 序列并在两个服务器上获得解释。 此时,您应该能够通过使用同一个客户端(即 SQLYOG)来重现问题,并且能够在重建索引或表后评估解释和性能的变化。如果目的是解决问题并生成有关将来如何再次修复它的文档,那么仅仅这样做并希望它会好起来并不是真的有用。 是的,当没有仔细的数据库维护计划时,由于需要重建索引而导致的性能下降通常会一次又一次地发生。
【讨论】:
【参考方案6】:这是我使用超大型数据库的个人经验,数据超过 800 万条记录。我不确定这有多大帮助,但就是这样。
对于非常大的记录,您尝试执行的查询会极大地影响响应所需的时间。例如,假设您正在尝试搜索名称为 "abc"
的产品并希望对其进行分页。
对于这两个查询将被执行。
-
第一个查询将计算所有以名称
abc
开头的记录,尽管是在您的数据库中。 - 假设音量很大,需要 10 秒,并且会从上到下。
执行第二次查询以获取您想要的前 10 或 20 条记录。这极大地影响了时间。
一个。假设您有很多名称为"abc"
的记录,那么查询将返回非常少的前 10 条记录,假设在 2 秒内返回。
b.但是,如果您的名称为“abc”的记录非常少,那么查询将一直传输到您的数据库,这将需要另外 10 秒,因此总执行时间现在是 20 秒,而第一种情况只有 12秒。
如果您想查看实际花费的时间,您可以使用laravel debugger tool
。它实际上显示正在执行哪些查询以及哪个查询花费了多少时间。
几乎没有其他因素,例如服务器设置和延迟。这些你也可以检查。
对于查询,我的建议n 将使用 simplePaginate()
,直到并且除非您想显示总记录。
希望这对您有所帮助。
【讨论】:
以上是关于一个数据库的查询速度很慢,但在他的副本上查询速度很快的主要内容,如果未能解决你的问题,请参考以下文章
为我的用户在 SO 上获得徽章的“等级” - 查询速度很慢 - 可以加速吗?