PolarDB有个sql能帮忙查下吗 这个sql用Statement Outline固定了执行计划 正常应该走指定的索引扫描2k多行数据 刚才触发了两次查询扫描了20多w数据 40多秒才查询出来
SELECT
sdt.produce_id,
sdt.customer_id,
sel.company_name AS company_name_m,
sel.prefix_domain_name,
sdt.products_id,
sdt.products_url_name,
SUBSTR(sdt.category_id, 1, 3) AS category_id_lv1,
sdt.produce_cas_no AS cas_no,
sdt.produce_name,
sdt.produce_url_name,
sdt.goods_picture_s,
sdt.goods_picture_m AS goods_picture,
sdt.goods_picture_b,
sdt.complete_flag,
sdt.hot_flag,
sdt.main_flag,
sdt.grade_name,
sdt.content,
sdt.package_name,
sdt.n_price_type,
sdt.n_price_trade_term_type,
sdt.n_price_trade_term_text,
sdt.n_price,
sdt.n_price_unit,
sdt.n_price_currency,
sdt.n_price_currency_symbol,
CASE
WHEN CEILING(IFNULL(sdt.n_min_price, 0)) = 0 THEN '0'
WHEN sdt.n_price_end_date < CURRENT_DATE() THEN '0'
ELSE '1'
END AS n_pending_flag,
sdt.activity_id,
sdt.activity_type,
sdt.a_price_trade_term_type,
sdt.a_price_trade_term_text,
sdt.a_price,
sdt.a_price_unit,
sdt.a_price_currency,
sdt.a_price_currency_symbol
FROM
t_e_all_produce_v1 sdt
INNER JOIN t_e_all_seller_v1 sel ON sdt.customer_id = sel.customer_id
WHERE
sdt.delflag = '0'
AND sel.delflag = '0'
AND sdt.customer_id = 'us20220607140012825'
AND sdt.products_id = 'pd2005121001'
AND sdt.produce_id != 'pr22121432843'
AND sdt.complete_flag = '1'
ORDER BY
sdt.produce_update_date DESC
limit 6
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
根据您提供的SQL语句和描述,该SQL在使用PolarDB的Statement Outline功能固定执行计划后,出现了异常情况:原本应通过指定索引扫描2k多行数据,但实际查询却扫描了20多万行数据,导致查询耗时40多秒。以下是针对此问题的详细分析和解决步骤。
首先需要确认Statement Outline是否正确应用到该SQL语句上。可以通过以下步骤验证:
使用dbms_outln.preview_outline
存储过程检查SQL是否匹配到已定义的Statement Outline规则:
CALL dbms_outln.preview_outline('your_schema_name', "SELECT sdt.produce_id, ...");
Hint
内容是否符合预期(例如是否指定了正确的索引)。使用dbms_outln.show_outline
查看内存中Statement Outline的命中情况:
CALL dbms_outln.show_outline();
Digest
值与Statement Outline规则中的Digest
值一致。State
为N
,则表示该规则未启用,需将其状态更新为Y
。使用EXPLAIN
命令查看SQL的实际执行计划,确认是否使用了指定的索引:
EXPLAIN SELECT sdt.produce_id, ...;
Index Scan
或Index Only Scan
),则说明Statement Outline未生效或存在其他问题。如果Statement Outline已生效,但执行计划仍不符合预期,可能是由于以下原因导致:
确保SQL中涉及的所有列均被索引覆盖。如果索引未完全覆盖查询条件或排序字段,优化器可能会选择全表扫描或其他非最优路径。
dbms_imci.check_columnar_index
检查SQL是否被列存索引完全覆盖:
CALL dbms_imci.check_columnar_index("SELECT sdt.produce_id, ...");
优化器可能基于查询代价评估选择了非最优路径。可以通过以下方式强制使用指定索引:
FORCE INDEX
提示:
SELECT /*+ FORCE INDEX(index_name) */ sdt.produce_id, ...;
SET loose_cost_threshold_for_imci = 0;
优化器的选择依赖于表的统计信息。如果统计信息过期或不准确,可能导致优化器选择错误的执行计划。
使用ANALYZE
命令更新表的统计信息:
ANALYZE TABLE t_e_all_produce_v1;
ANALYZE TABLE t_e_all_seller_v1;
确认customer_id
、products_id
等过滤条件的值是否具有高选择性。如果这些字段的值分布不均匀,可能导致优化器低估索引扫描的效率。
如果您的PolarDB实例启用了列存节点,但SQL未被转发至列存节点,也可能导致性能问题。
确认数据库连接地址中是否包含只读列存节点,并确保loose_cost_threshold_for_imci
参数设置合理。
在SQL中添加/*FORCE_IMCI_NODES*/
提示,强制将SQL转发至列存节点:
/*FORCE_IMCI_NODES*/ EXPLAIN SELECT sdt.produce_id, ...;
如果上述步骤均未解决问题,可以尝试重新定义或调整Statement Outline规则。
删除当前的Statement Outline规则:
CALL dbms_outln.del_outline(<Id>);
重新添加Statement Outline规则,确保Hint
内容明确指定索引:
CALL dbms_outln.add_index_outline(
'your_schema_name',
'',
1,
'USE INDEX',
'index_name',
'',
"SELECT sdt.produce_id, ..."
);
如果问题仍未解决,请提供以下信息以便进一步排查: 1. EXPLAIN
输出的完整执行计划。 2. 当前Statement Outline规则的定义(包括Hint
内容)。 3. 表的索引结构及统计信息。
希望以上步骤能帮助您快速定位并解决问题!
阿里云关系型数据库主要有以下几种:RDS MySQL版、RDS PostgreSQL 版、RDS SQL Server 版、PolarDB MySQL版、PolarDB PostgreSQL 版、PolarDB分布式版 。