[英]Slow query at one DB, but fast at his copy
我們有一個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。
我有3個解決方案:
1)使用以下命令檢查並優化和修復表:
mysqlcheck -u root -p --auto-repair --check --optimize --all-databases
2)如果問題未解決,請使用Newrelic等監控應用檢查您的查詢執行計划
3)有時它不是關於數據庫損壞的特定表,嘗試刪除並創建一個舊數據的新表。 如何恢復/重新創建mysql的默認'mysql'數據庫
您是否嘗試在實時數據庫上重建索引?
在MySQL中,這可以通過REPAIR <table> QUICK
命令完成(快速修復 - 意味着只修復索引 - 重建它們)。
(請在應用之前備份數據庫...此命令幾乎沒有機會破壞數據庫,但......)
一些額外的解釋:
Mysql主要使用自平衡B +樹作為索引,他們試圖盡可能地保持平坦,以提供良好的搜索時間。
但在某些情況下(通常它與增加數據插入DATETIME列有關,例如createdAt
with index)MySQL B +樹實現無法處理這種類型的負載。 生成的樹提供的性能在一段時間(幾天,幾周)內不斷降低。 這些索引必須重建......
如果這種方法可以幫助你 - 每x
天重建索引一次(每周一次為我工作)
可能有幾個問題,一個是重建索引,在此之前已經解決並做了備份,
另一個是你正在運行的服務器,我的意思是Apache或NGINX。
看看為什么運行apache
ps auxf
通過打開服務器狀態來監控apache
apachectl fullstatus
您需要修復您的數據庫。
為什么要壓縮和修復數據庫
此概述說明了如何使用“壓縮和修復數據庫”命令來幫助防止和糾正有時會影響數據庫的以下問題:文件隨着使用而變大,文件也會損壞。
數據庫文件隨着使用而增長當您添加和更新數據並更改其設計時,數據庫文件會變得更大。 其中一些增長來自新數據,但有些來自其他來源:
Access創建臨時隱藏對象以完成各種任務。 有時,Access不再需要它們后,這些臨時對象仍保留在數據庫中。
刪除數據庫對象時,不會自動回收對象占用的磁盤空間 - 即使刪除了對象,數據庫文件仍會使用該磁盤空間。
當您的數據庫文件填滿臨時和已刪除對象的剩余部分時,其性能可能會降低。 對象可能打開得更慢,查詢可能需要比正常運行更長的時間,並且典型操作通常需要更長時間。
參考:
沒有足夠的信息來提供詳細的診斷。 就個人而言,當查詢執行緩慢時,我會開始檢查服務器上的內存和CPU占用情況,htop是一個很好的工具,以防你無法訪問任何其他許可軟件進行服務器監控,只是為了確保不僅僅是機器是平等的,但也是工作量。 很多時候,這類問題取決於鎖定或資源爭用,而不是來自特定查詢。 最終隔離一個sql序列並在服務器上獲取解釋。 此時,您應該能夠通過使用相同的客戶端(即SQLYOG)來重現該問題,並且能夠在重建索引或表之后評估解釋和性能的更改。 只是為了做到這一點,並希望如果目的是解決問題並生成有關如何在將來再次修復它的文檔,它將會很好。 是的,當一個仔細的數據庫維護程序沒有到位時,由於需要重建的索引而導致的性能下降通常會一次又一次地發生。
以下是我使用超大型數據庫的個人經驗,其中包含超過800萬條記錄的數據。 我不確定這有多大幫助,但現在確實如此。
對於非常大的記錄,您嘗試執行的查詢會極大地影響響應所花費的時間。 例如,讓我們說,如果您正在嘗試搜索名為"abc"
並想要對其進行分頁。 為此,將執行兩個查詢。
abc
開頭的所有記錄,盡管數據庫已經存在。 - 假設自音量高以來需要10秒,它將從上到下。 第二個查詢執行以獲取您想要的前10或20條記錄。 這極大地影響了時間。
一個。 假設您有很多名稱為"abc"
的記錄,那么查詢將返回前10個記錄的非常少,讓我們說在2秒內。
灣 但是如果你的記錄名稱為“abc”的記錄非常少,那么查詢將一直傳到你的數據庫,它還需要10秒,所以總的執行時間現在是20秒,而第一種情況只有12秒秒。
如果你想看看實際花費的時間,你可以使用laravel debugger tool
。這實際上顯示了正在執行的查詢以及需要花費多少時間的查詢。
幾乎沒有其他因素,如服務器設置和延遲。 那些你也可以檢查。
對於查詢,我的建議是使用simplePaginate()
,直到除非你想顯示總記錄。
希望這對你有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.