在我正在开发的一个网络应用程序中,有一个UPDATE
正在减慢/阻止其他几个查询:
UPDATE products
SET visible = 1
WHERE merchant_id = in_merchant_id
AND source_code IN (
SELECT source_code
FROM feeds_processing_data
WHERE processing_id = in_processing_id
)
Run Code Online (Sandbox Code Playgroud)
它基本上更新了桌子上的特定“窗口” products
,根据其他一些信息打开或关闭可见性。该表是 Web 应用程序的核心,来自前端的搜索在其中运行(通过全文或通过代码查找),后台进程会不时更新其内容。
我通常通过检查查询计划并验证是否存在正确的索引来解决这些问题。
然而,令我困惑的是,列出的会话information_schema.PROCESSLIST
显示上述查询位于该preparing
状态,而其他被阻止的查询是Waiting for table flush
,我对此知之甚少或一无所知。
这是被阻止的查询之一:
SELECT id,
[...]
FROM (
SELECT (MATCH(NAME, description, manufacturer_name) AGAINST('+crema +mani' IN BOOLEAN MODE)) AS rank,
p.*
FROM products p
WHERE visible = 1
AND MATCH(NAME, description, manufacturer_name) AGAINST('+crema +mani' IN BOOLEAN MODE) LIMIT 400
) ranked
ORDER BY final_price
Run Code Online (Sandbox Code Playgroud)
乍一看,我认为没有任何问题UPDATE
,这是它的EXPLAIN
计划:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY products range uk_merchant_id_source_code uk_merchant_id_source_code 4 const 3861 Using where
2 DEPENDENT SUBQUERY feeds_processing_data ref fk_processing,source_code fk_processing 4 const 2 Using where
Run Code Online (Sandbox Code Playgroud)
相关表的索引如下。
SHOW INDEXES FROM products
:
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
products 0 PRIMARY 1 id A 409324 NULL NULL BTREE
products 0 uk_merchant_id_source_code 1 merchant_id A 126 NULL NULL BTREE
products 0 uk_merchant_id_source_code 2 source_code A 409324 NULL NULL BTREE
products 1 visible 1 visible A 2 NULL NULL BTREE
products 1 gtin 1 gtin A 409324 NULL NULL YES BTREE
products 1 industry_code 1 industry_code A 409324 NULL NULL YES BTREE
products 1 name_description_manufacturer_name 1 name NULL 409324 NULL NULL YES FULLTEXT
products 1 name_description_manufacturer_name 2 description NULL 409324 NULL NULL YES FULLTEXT
products 1 name_description_manufacturer_name 3 manufacturer_name NULL 409324 NULL NULL YES FULLTEXT
Run Code Online (Sandbox Code Playgroud)
SHOW INDEXES FROM feeds_processing_data
:
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
feeds_processing_data 0 PRIMARY 1 id A 10336188 NULL NULL BTREE
feeds_processing_data 1 fk_processing 1 processing_id A 2981 NULL NULL BTREE
feeds_processing_data 1 source_code 1 source_code A 136002 NULL NULL YES BTREE
feeds_processing_data 1 rejected 1 rejected A 1 NULL NULL BTREE
Run Code Online (Sandbox Code Playgroud)
我无法解决的第一个问题是:为什么要花这么多时间才能完成准备阶段?
那么,如何进一步排查问题呢?我在这里缺少什么信息?
正如 @jkavalik 所写,您正在使用依赖子查询执行更新,该子查询有效地运行了 3861 次,即使查询本身运行得很快,它也非常低效。
查询的更新版本可能是:
UPDATE products
JOIN feeds_processing_data ON
(product.source_code = feeds_processing_data.source_code
AND ?.processing_id = ?.in_processing_id)
SET products.visible = 1
WHERE merchant_id = in_merchant_id
Run Code Online (Sandbox Code Playgroud)
您没有附加表模式,所以我只是假设这会起作用。您可能需要完全限定字段名称(使用 tablename.fieldname)。feeds_processing_data 还可以受益于覆盖所涉及字段的复合索引。