MySQL 5.7 優化不能只看執行計劃
就這麼一條SQL要40s,看執行計劃,發現rows很小,神奇了。
SELECT T1.* FROM
(SELECT
T.*,
R.LOCATION_DEPART_ID AS locationDepartId,
CASE
WHEN T.INVENTORY_TYPE = 1
THEN f_fm_getFullLocationName(R.LOCATION_DEPART_ID, '50000050')
WHEN T.INVENTORY_TYPE = 2
THEN
(SELECT f_gg_org_getorgnamepath(OT.ORG_ID,'50000050',ot.org_name)
FROM gg_ORGANIZATION OT
WHERE OT.ORG_ID = R.LOCATION_DEPART_ID)
ELSE ''
END AS locationOrOrgName,
CASE
WHEN T.INVENTORY_TYPE = 1
THEN f_fm_getFullClassifyName (R.CLASSIFY_ID)
ELSE ''
END AS classifyName,
(SELECT
COUNT(
CASE
WHEN ii.INVENTORY_RESULT = 1 THEN 1
END
)
FROM
FM_INVENTORY I,
FM_INVENTORY_ITEM II
WHERE I.ID = II.INVENTORY_ID
AND I.TASK_ID = T.ID) AS waitInventoryNum
FROM
FM_INVENTORY_TASK T,
FM_INVENTORY_TASK_RANGE R
WHERE T.ID = R.TASK_ID) T1
WHERE 1 = 1
AND T1.FLOW_STATE = 2;
id select_type table type key key_len ref rows Extra
-- ------------------ ---------- ------ -------------------- ------- ------------------- ------ -----------
1 PRIMARY <derived2> ref <auto_key0> 2 const 8 (NULL)
2 DERIVED T ALL (NULL) (NULL) (NULL) 80 (NULL)
2 DERIVED R ref IDX_RANGE_TASK_ID 111 T.ID 1 (NULL)
4 DEPENDENT SUBQUERY I ref IDX_INV_TASK_ID 110 T.ID 1 Using index
4 DEPENDENT SUBQUERY II ref IDX_INV_INVENTORY_ID 110 I.ID 6 (NULL)
3 DEPENDENT SUBQUERY OT eq_ref PRIMARY 98 R.LOCATION_DEPART_ID 1 Using where
第一個感覺是資料庫快取的問題,檢查了一下,很多配置都是預設的,於是加了一下。
[mysqld]下面新增
innodb_read_io_threads = 16
innodb_write_io_threads = 16
max_heap_table_size = 159M
tmp_table_size = 159M
sort_buffer_size = 8M
join_buffer_size = 8M
read_buffer_size = 4M
read_rnd_buffer_size = 16M
bulk_insert_buffer_size = 64M
innodb_buffer_pool_instances = 8
innodb_file_per_table = 1
innodb_thread_concurrency = 0
innodb_log_buffer_size = 6M
innodb_log_file_size = 256M
重啟資料庫之後,發現效能有所提升,還是30s。只能用最傳統的辦法,把子查詢一個個去掉,執行,發現第三個子查詢去掉之後秒出。
(SELECT
COUNT(
CASE
WHEN ii.INVENTORY_RESULT = 1 THEN 1
END
)
FROM
FM_INVENTORY I,
FM_INVENTORY_ITEM II
WHERE I.ID = II.INVENTORY_ID
AND I.TASK_ID = T.ID) AS waitInventoryNum
用show profiles診斷髮現時間耗在send data上面。
檢查了一下FM_INVENTORY_ITEM是明細的資料,接近800萬的資料,且大部分資料集中在一個單上。找了下業務,發現是異常問題,把垃圾資料遷移出去,然後執行SQL,秒出。
總結:MySQL裡面的執行計劃比較弱,有時候不能完全依賴,還是得查每張表實際的大小。
SELECT T1.* FROM
(SELECT
T.*,
R.LOCATION_DEPART_ID AS locationDepartId,
CASE
WHEN T.INVENTORY_TYPE = 1
THEN f_fm_getFullLocationName(R.LOCATION_DEPART_ID, '50000050')
WHEN T.INVENTORY_TYPE = 2
THEN
(SELECT f_gg_org_getorgnamepath(OT.ORG_ID,'50000050',ot.org_name)
FROM gg_ORGANIZATION OT
WHERE OT.ORG_ID = R.LOCATION_DEPART_ID)
ELSE ''
END AS locationOrOrgName,
CASE
WHEN T.INVENTORY_TYPE = 1
THEN f_fm_getFullClassifyName (R.CLASSIFY_ID)
ELSE ''
END AS classifyName,
(SELECT
COUNT(
CASE
WHEN ii.INVENTORY_RESULT = 1 THEN 1
END
)
FROM
FM_INVENTORY I,
FM_INVENTORY_ITEM II
WHERE I.ID = II.INVENTORY_ID
AND I.TASK_ID = T.ID) AS waitInventoryNum
FROM
FM_INVENTORY_TASK T,
FM_INVENTORY_TASK_RANGE R
WHERE T.ID = R.TASK_ID) T1
WHERE 1 = 1
AND T1.FLOW_STATE = 2;
id select_type table type key key_len ref rows Extra
-- ------------------ ---------- ------ -------------------- ------- ------------------- ------ -----------
1 PRIMARY <derived2> ref <auto_key0> 2 const 8 (NULL)
2 DERIVED T ALL (NULL) (NULL) (NULL) 80 (NULL)
2 DERIVED R ref IDX_RANGE_TASK_ID 111 T.ID 1 (NULL)
4 DEPENDENT SUBQUERY I ref IDX_INV_TASK_ID 110 T.ID 1 Using index
4 DEPENDENT SUBQUERY II ref IDX_INV_INVENTORY_ID 110 I.ID 6 (NULL)
3 DEPENDENT SUBQUERY OT eq_ref PRIMARY 98 R.LOCATION_DEPART_ID 1 Using where
第一個感覺是資料庫快取的問題,檢查了一下,很多配置都是預設的,於是加了一下。
[mysqld]下面新增
innodb_read_io_threads = 16
innodb_write_io_threads = 16
max_heap_table_size = 159M
tmp_table_size = 159M
sort_buffer_size = 8M
join_buffer_size = 8M
read_buffer_size = 4M
read_rnd_buffer_size = 16M
bulk_insert_buffer_size = 64M
innodb_buffer_pool_instances = 8
innodb_file_per_table = 1
innodb_thread_concurrency = 0
innodb_log_buffer_size = 6M
innodb_log_file_size = 256M
重啟資料庫之後,發現效能有所提升,還是30s。只能用最傳統的辦法,把子查詢一個個去掉,執行,發現第三個子查詢去掉之後秒出。
(SELECT
COUNT(
CASE
WHEN ii.INVENTORY_RESULT = 1 THEN 1
END
)
FROM
FM_INVENTORY I,
FM_INVENTORY_ITEM II
WHERE I.ID = II.INVENTORY_ID
AND I.TASK_ID = T.ID) AS waitInventoryNum
用show profiles診斷髮現時間耗在send data上面。
檢查了一下FM_INVENTORY_ITEM是明細的資料,接近800萬的資料,且大部分資料集中在一個單上。找了下業務,發現是異常問題,把垃圾資料遷移出去,然後執行SQL,秒出。
總結:MySQL裡面的執行計劃比較弱,有時候不能完全依賴,還是得查每張表實際的大小。
相關文章
- 【MySQL】MySQL的執行計劃及索引優化MySql索引優化
- 分析執行計劃優化SQLORACLE的執行計劃(轉)優化SQLOracle
- mysql調優之——執行計劃explainMySqlAI
- MySQL優化從執行計劃開始(explain超詳細)MySql優化AI
- MySQL查詢優化之優化器工作流程以及優化的執行計劃生成MySql優化
- MySQL執行計劃MySql
- MySQL 執行計劃MySql
- MySQL執行計劃解析MySql
- mysql explain 執行計劃MySqlAI
- mysql執行計劃explainMySqlAI
- MySQL Cases-執行計劃向Oracle看齊(FORMAT=tree)MySqlOracleORM
- MySQL調優篇 | EXPLAIN執行計劃解讀(4)MySqlAI
- 不會看 Explain執行計劃,勸你簡歷別寫熟悉 SQL優化AISQL優化
- 不會看 Explain 執行計劃,勸你簡歷別寫熟悉 SQL 優化AISQL優化
- MySQL執行計劃解析(四)MySql
- 讀懂MySQL執行計劃MySql
- [20230130]toad看執行計劃注意.txt
- mysql explain 執行計劃詳解MySqlAI
- 十六、Mysql之Explain執行計劃MySqlAI
- MySQL Explain執行計劃 - 詳解MySqlAI
- 帶你看懂MySQL執行計劃MySql
- PostgreSQL執行計劃變化SQL
- mysql 5.7 執行緒阻塞處理MySql執行緒
- (4) MySQL中EXPLAIN執行計劃分析MySqlAI
- mysql主從庫執行計劃不同MySql
- mysql 執行計劃索引分析筆記MySql索引筆記
- SQL優化案例-從執行計劃定位SQL問題(三)SQL優化
- Oracle優化案例-從執行計劃定位SQL問題(三)Oracle優化SQL
- Calcite執行計劃最佳化
- 執行計劃-1:獲取執行計劃
- [20181120]toad看真實的執行計劃.txt
- Oracle調優之看懂Oracle執行計劃Oracle
- Ubuntu 18.04不能裝 MySQL5.7UbuntuMySql
- MySQL explain執行計劃詳細解釋MySqlAI
- Oracle優化案例-統計資訊對執行計劃的影響(十三)Oracle優化
- [20191220]格式化執行計劃.txt
- TiDB 查詢優化及調優系列(四)查詢執行計劃的調整及優化原理TiDB優化
- 分析執行計劃優化SQLSQL語句處理的過程(轉)優化SQL