在一个数据库上查询速度慢,但在他的副本上查询速度快

Slow query at one DB, but fast at his copy

我们有一个 Laravel 应用程序(版本 5.4.18)连接到 MySQL (5.6.38) 数据库(总共 30 万行),MyISAM 类型。 并且我们有 api-response 像 Model::with('anothermodel')->paginate(25),并且在某个时候这个查询的执行时间已经达到 18 秒,这是非常大的价值。我创建了一个带有实时 laravel 环境副本的沙箱,该环境使用完全相同的数据库(在同一台服务器上)的副本,现在这个 api-响应在 2.5 秒内执行。如果我们尝试将沙箱 laravel 连接到实时数据库,那么 api 执行又是 18 秒。请检查图像。

因此,如果我们假设问题出在实时网站的数据库 table 中,但如果我们尝试使用 microtime 来衡量此查询,那么它会显示生成此查询所需的时间从数据库查询和抓取数据仅需0.7秒

因此,如果我们假设问题出在 API 路由或 Laravel 代码中,但是如果我只是将它复制到子目录(作为沙箱),则执行完全相同的代码没有任何问题).

有什么想法吗?

还有一些服务器信息:PHP 7.0.29 在 Linux 服务器上,内存为 32gb。

您是否尝试过在实时数据库上重建索引?

在 MySQL 中,这可以通过 REPAIR <table> QUICK 命令完成(快速修复 - 意味着只修复索引 - 重建它们)。

(申请前请先备份数据库...这个命令几乎没有机会破坏数据库,但是...)


补充说明:

Mysql 主要使用自平衡 B+ 树作为索引,他们试图尽可能地平坦以提供良好的搜索时间。

但在某些情况下(通常与向 DATETIME 列中的增量数据插入有关,例如 createdAt 带有索引)MySQL B+ 树实现无法处理此类负载。生成的树提供的性能会随着时间(数天、数周)不断下降。必须重建此类索引...

如果这种方法对您有帮助 - 每 x 天重建一次索引(上次我每周一次)

可能有几个问题,一个是重建索引,已解决并在此之前做好备份,

另一个是你的服务器运行,我指的是Apache或者NGINX

看看 Apache 的 运行 是什么

ps auxf

通过打开服务器状态来监控 Apache

apachectl fullstatus

A good read here on Apache performance

我有 3 个解决方案供您选择:

1) 使用此命令检查并优化并修复 table:

mysqlcheck -u root -p --auto-repair --check --optimize --all-databases

2) 如果问题没有解决,请使用 Newrelic

等监控应用程序检查您的查询执行计划

3) 有时这与特定的 table 无关,而是与数据库损坏有关,请尝试删除旧数据并创建一个新数据。 How to recover/recreate mysql's default 'mysql' database

您需要修复数据库。

为什么压缩和修复数据库

此概述说明了使用“压缩和修复数据库”命令如何帮助预防和纠正有时会影响数据库的以下问题:文件随着使用而变大和文件损坏。

数据库文件随着使用而增长 当您添加和更新数据并更改其设计时,数据库文件会变得更大。这种增长部分来自新数据,但部分来自其他来源:

  • Access 创建临时的隐藏对象来完成各种任务。 有时,这些临时对象在之后仍保留在您的数据库中 Access 不再需要它们。

    当您删除一个数据库对象时,该对象所在的磁盘space 占用不会自动回收——数据库文件仍然 使用该磁盘 space,即使对象已删除。

当您的数据库文件中充满了临时对象和已删除对象的剩余部分时,其性能可能会下降。对象打开速度可能会更慢,查询可能需要比正常时间更长的时间 运行,而典型操作通常似乎需要更长的时间。

参考:

https://support.office.com/en-us/article/Compact-and-repair-a-database-6ee60f16-aed0-40ac-bf22-85fa9f4005b2

信息不足,无法进行详细诊断。 就我个人而言,当查询执行缓慢时,我会开始检查服务器上的内存和 cpu 占用情况,htop 是一个很好的工具,以防您无法访问任何其他用于服务器监控的许可软件,只是为了确定不仅机器是平等的,而且工作量也是平等的。 很多时候,此类问题取决于锁定或资源争用,而不是特定查询。 最终分离出一个 sql 序列并在两个服务器上得到解释。 此时,您应该能够通过使用相同的客户端(即 SQLYOG)来重现问题,并且能够在重建索引或表后评估解释和性能的变化。如果目的是解决问题并生成有关如何在将来再次修复它的文档,那么仅仅去做并希望它会好起来并没有多大用处。 是的,当没有仔细的数据库维护程序时,通常会因为需要重建索引而导致性能下降。

以下是我使用超大型数据库的个人经验,数据超过 800 万条记录。我不确定这有多少帮助,但在这里。

对于非常大的记录,您尝试执行的查询会极大地影响响应所需的时间。例如,假设您正在尝试搜索名称为 "abc" 的产品并希望对其进行分页。 为此将执行两个查询。

  1. 第一个查询将计算数据库中以名称 abc 开头的所有记录。 - 可以说这花了 10 秒,因为音量很高,而且它会从上到下。
  2. 执行第二个查询以获取您想要的前 10 条或 20 条记录。这极大地影响了时间。

    一个。假设您有很多名称为 "abc" 的记录,那么查询将 return 前 10 条记录非常少,假设在 2 秒内。

    b。但是,如果您的名称为 "abc" 的记录非常少,那么查询将一直传输到您的数据库,这将再花费 10 秒,因此现在总执行时间为 20 秒,而第一种情况是仅12秒

如果您想查看实际花费的时间,可以使用 laravel debugger tool。这实际上显示了正在执行的查询以及哪个查询花费了多少时间。

几乎没有其他因素,例如服务器设置和延迟。那些你也可以检查。

对于查询,我的建议n 将使用 simplePaginate() ,直到并且除非你想显示总记录。

希望对您有所帮助。