Mysql

呼叫其他查詢後,相同的查詢會變慢(在儲存過程中使用大量準備好的語句)

  • June 24, 2019

我有一個查詢,當我在重新啟動 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 計數更接近各自的準備計數時,更有可能實現一致的查詢執行速度。

正常 日誌擷取和分析將確認資源仍在使用中且未被釋放或關閉。

免責聲明:我是我的個人資料中提到的網站的內容作者,網路個人資料包括免費實用程序腳本和聯繫資訊。

引用自:https://dba.stackexchange.com/questions/240005