我们有一个Laravel应用程序(版本5.4.18),它连接到MySQL(5.6.38)数据库(总共300k行),MyISAM类型。
我们有像Model::with('anothermodel')->paginate(25)
这样的api-response,并且在某些时候这个查询的执行时间已达到18秒,这是非常大的值。我创建了一个沙盒,其中包含使用exaclty相同数据库(在同一服务器上)的副本的实时laravel环境,现在这个api-response在2.5秒内执行。如果我们尝试将沙盒laravel连接到实时DB,那么api执行再次是18s。请检查图像。
因此,如果我们假设问题出现在实时网站的数据库表中,但如果我们尝试使用microtime
来衡量此查询,那么它将显示生成此查询所需的时间并从中获取数据数据库只有0.7秒。
因此,如果我们假设问题出现在API路由或Laravel代码中,但如果我只是将其复制到子目录(作为沙箱),那么执行相同的代码没有任何问题。
有什么想法吗?
还有一些服务器信息:Linux服务器上的PHP 7.0.29,内存为32GB。
答案 0 :(得分:2)
我有3种解决方案:
1)检查&优化与优化使用以下命令修复表:
mysqlcheck -u root -p --auto-repair --check --optimize --all-databases
2)如果问题未解决,请使用Newrelic
等监控应用检查您的查询执行计划3)有时它不是关于数据库损坏的特定表,尝试删除并创建一个包含旧数据的新表。 How to recover/recreate mysql's default 'mysql' database
答案 1 :(得分:1)
您是否尝试在实时数据库上重建索引?
在MySQL中,这可以使用REPAIR <table> QUICK
命令完成(快速修复 - 意味着只修复索引 - 重建它们)。
(请在申请前备份数据库......此命令几乎没有机会破坏数据库,但是......)
一些额外的解释:
Mysql主要使用自平衡B +树作为索引,它们尽可能地保持最平坦,以提供良好的搜索时间。
但在某些情况下(通常它与DATETIME列中的增量数据插入有关,例如带有索引的createdAt
)MySQL B +树实现无法处理这种类型的负载。生成的树提供的性能在一段时间(几天,几周)内不断降低。这些索引必须重建......
如果这种方法可以帮助您 - 每x
天重建一次索引(上周每周一次为我工作)
答案 2 :(得分:1)
可能有几个问题,一个是重建索引,已解决并在此之前进行备份,
另一个是您正在运行的服务器,我的意思是Apache或NGINX。
查看针对apache运行的内容
ps auxf
通过启用服务器状态
来监控apacheapachectl fullstatus
答案 3 :(得分:1)
您需要修复数据库。
为什么要压缩和修复数据库
此概述说明了如何使用“压缩和修复数据库”命令来帮助防止和纠正有时会影响数据库的以下问题:文件随着使用而变大,文件也会损坏。
数据库文件随着使用而增长 在添加和更新数据并更改其设计时,数据库文件会变大。其中一些增长来自新数据,但有些来自其他来源:
Access创建临时隐藏对象以完成各种任务。 有时,这些临时对象之后会保留在您的数据库中 访问不再需要它们。
删除数据库对象时,该对象的磁盘空间 占用不会自动回收 - 数据库文件仍然存在 使用该磁盘空间,即使该对象已被删除。
当您的数据库文件填满临时和已删除对象的剩余部分时,其性能可能会降低。对象可能打开得更慢,查询运行时间可能比正常情况要长,典型操作通常需要更长的时间。
参考:
答案 4 :(得分:1)
没有足够的信息来提供详细的诊断。 就个人而言,当查询执行缓慢时,我会开始检查服务器上的内存和CPU占用情况,htop是一个很好的工具,以防你无法访问任何其他许可软件进行服务器监控,只是为了确保不仅仅是机器是平等的,但也是工作量。 很多时候,这类问题取决于锁定或资源争用,而不是来自特定查询。 最终隔离一个sql序列并在服务器上获取解释。 此时,您应该能够通过使用相同的客户端(即SQLYOG)来重现该问题,并且能够在重建索引或表之后评估解释和性能的更改。只是为了做到这一点,并希望如果目的是解决问题并生成有关如何在将来再次修复它的文档,它将会很好。 是的,当一个仔细的数据库维护计划没有到位时,由于需要重建的索引而导致的性能下降通常会一次又一次地发生。
答案 5 :(得分:1)
以下是我使用超大型数据库的个人经验,数据超过800万条记录。我不确定这有多大帮助,但现在就是。
对于非常大的记录,您尝试执行的查询会极大地影响响应所花费的时间。例如,如果您尝试搜索名称为"abc"
的产品并希望对其进行分页,则可以这样说。
为此,将执行两个查询。
abc
开头的所有记录,尽管您的数据库已经存在。 - 假设自音量高以来需要10秒,它将从上到下。执行第二次查询以获取您想要的前10或20条记录。这极大地影响了时间。
一个。假设您有很多名称为"abc"
的记录,那么查询将返回前10个记录的非常少,让我们说在2秒内。
湾但是如果你的记录名称为“abc”的记录非常少,那么查询将一直传到你的数据库,它还需要10秒,所以总的执行时间现在是20秒,而第一种情况只有12秒秒
如果你想知道实际花费的时间,你可以使用laravel debugger tool
。这实际上显示了正在执行的查询以及需要花费多少时间的查询。
其他因素很少,例如服务器设置和延迟。那些你也可以检查。
对于查询我的建议 n将使用simplePaginate()
,直到除非您想要显示总记录。
希望这对你有所帮助。