呼叫其他查詢後,相同的查詢會變慢(在儲存過程中使用大量準備好的語句)
我有一個查詢,當我在重新啟動 mysql 後第一次執行它時,需要 2 秒,但是當我在它之前執行一系列其他查詢時(這個查詢屬於其他程序之間的一個程序)突然查詢需要大約 2 分鐘,如果我重新啟動 mysql 並重新執行它,它又需要 2 秒。
持續時間幾乎相同(~2 秒和~2 分鐘),所以即使它變慢也不是隨機的,特別是這個查詢變慢了(或者可能是這個表),其他一切都是正常的。
- 已禁用
query_cache
- 增加
innodb_buffer_pool_size
(我認為它與記憶體或緩衝區變滿有關,使下一個查詢變慢)- 檢查鎖表
我不知道查詢會影響它之後的另一個查詢/表(數據除外)。
有什麼可以搜尋的路徑或可以嘗試的東西嗎,我對要搜尋的內容沒有任何線索。
我正在使用 MySQL 5.7 版
解釋計劃是
我實際上發現問題不在於特定的表,而只是準備好的語句太多
+--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | Com_prepare_sql | 60 | | Com_stmt_prepare | 82 | | Com_xa_prepare | 0 | | Com_stmt_reprepare | 24 | +--------------------+-------+
文件中提到
A prepared statement is also global to the session. If you create a prepared statement within a stored routine, it is not deallocated when the stored routine ends.
我認為這意味著它們應該被明確地釋放,但顯然情況並非如此。
insert into s__demand_table_14_0(year, hospital_id, disease_id, nb_patients) SELECT fcbf_parent.year, table_referral.to_hospital_id, table_referral.disease_id, SUM(ifnull(fcbf_parent.nb_patients, 0) * ifnull(table_referral.ratio_of_referrals * (1 + ifnull(ir.ratio_of_referrals, 0)), 0)) + ifnull(SUM(fcbf.nb_patients), 0) AS referred_patients FROM table_hospital bf_current join table_hospital bf_parent on bf_parent.type = ? or bf_parent.type = ? LEFT JOIN table_referral ON bf_current.type = ? and table_referral.to_hospital_id = bf_current.id and table_referral.from_hospital_id = bf_parent.id JOIN s__demand_catchment_by_hospital_14_0 fcbf_parent on fcbf_parent.disease_id = table_referral.disease_id and fcbf_parent.hospital_id = bf_parent.id and fcbf_parent.nb_patients > 0 LEFT JOIN s__demand_catchment_by_hospital_14_0 fcbf on fcbf.disease_id = table_referral.disease_id and fcbf.hospital_id = bf_current.id left join s__intermediate_referral_14_0 ir on (ir.from_hospital_type = ? OR ir.from_hospital_type = ?) and ir.to_hospital_type = ? and ir.year = fcbf_parent.year and ir.disease_id = table_referral.disease_id where bf_current.type = ? GROUP BY fcbf_parent.year, table_referral.to_hospital_id, table_referral.disease_id;
SHOW GLOBAL STATUS LIKE 'com_%_sql';
| Variable_name | Value | +-----------------+-------+ | Com_dealloc_sql | 25 | | Com_execute_sql | 76 | | Com_prepare_sql | 50 | +-----------------+-------+ SHOW GLOBAL STATUS LIKE 'com_stmt_%'; +-------------------------+-------+ | Variable_name | Value | +-------------------------+-------+ | Com_stmt_execute | 100 | | Com_stmt_close | 48 | | Com_stmt_fetch | 0 | | Com_stmt_prepare | 74 | | Com_stmt_reset | 0 | | Com_stmt_send_long_data | 0 | | Com_stmt_reprepare | 24 | +-------------------------+-------+
RAM沒有發生巨大變化
解釋計劃
+----+-------------+---------------+------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------+---------+------------------------------------------------+-------+----------+----------------------------------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------+------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------+---------+------------------------------------------------+-------+----------+----------------------------------------------------+ | 1 | SIMPLE | bf_parent | NULL | ref | PRIMARY,base_facili_type_6d98f9_idx | base_facili_type_6d98f9_idx | 257 | const | 1 | 100.00 | Using index; Using temporary; Using filesort | | 1 | SIMPLE | fcbf_parent | NULL | ALL | NULL | NULL | NULL | NULL | 19142 | 3.33 | Using where; Using join buffer (Block Nested Loop) | | 1 | SIMPLE | base_referral | NULL | ref | referral_disease_id_ad6e6e71_fk_disease_icd_code,referral_from_facility_id_b9840c9f_fk_facility_id,referral_to_facility_id_81a49e98_fk_facility_id,base_referr_disease_b74959_idx,base_referr_disease_9bbdaf_idx | referral_disease_id_ad6e6e71_fk_disease_icd_code | 257 | capacity_planning.fcbf_parent.disease_id | 3 | 100.00 | Using where | | 1 | SIMPLE | bf_current | NULL | eq_ref | PRIMARY,base_facili_type_6d98f9_idx | PRIMARY | 4 | capacity_planning.base_referral.to_facility_id | 1 | 57.14 | Using where | | 1 | SIMPLE | fcbf | NULL | ALL | NULL | NULL | NULL | NULL | 19142 | 100.00 | Using where; Using join buffer (Block Nested Loop) | | 1 | SIMPLE | ir | NULL | ALL | forecast_intermediat_disease_id_689b0572_fk_disease_i | NULL | NULL | NULL | 1 | 100.00 | Using where; Using join buffer (Block Nested Loop) | +----+-------------+---------------+------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------+---------+------------------------------------------------+-------+----------+----------------------------------------------------+
通過執行以下 3 個步驟,我終於能夠顯著減少時間:
- 刪除了多餘的索引
- 在每個過程開始時刪除自動送出、外鍵檢查和唯一檢查
- 將我正在填充的表的儲存引擎更改為 MyISAM。
您的 com_prepare_sql 為 50,com_dealloc_sql 為 25,這意味著您已將 RESOURCES 留在 USE 中,因為 CLOSE() 沒有表示您已完成該過程。
您的 com_stmt_prepare 為 72,com_stmt_close 為 48,這意味著您已將 RESOURCES 留在 USE 中,因為 CLOSE() 沒有表示您已完成該過程。
當 dealloc 和 close 計數更接近各自的準備計數時,更有可能實現一致的查詢執行速度。
正常 日誌擷取和分析將確認資源仍在使用中且未被釋放或關閉。
免責聲明:我是我的個人資料中提到的網站的內容作者,網路個人資料包括免費實用程序腳本和聯繫資訊。