商品加入购物车、修改数量或进入结账都要等待数秒,性能跟踪显示 SalesRule 占用大量时间。购物车价格规则会在 collect totals 时反复验证,规则数量、条件复杂度和购物车行数相乘后,开销会快速扩大。
先确认慢请求是否重复 collect totals
一个正常操作可能因地址、运费、支付或自定义组件触发多次 totals。记录同一请求中 collector 的执行次数。第三方一步结账如果每个字段变化都保存 Quote 并重算,优化单条规则也无法解决整体抖动。
统计当前真正有效的规则
后台长期积累的停用或过期规则通常不应参与,但配置错误、日期和 Website 范围会让规则仍被加载。检查当前时间、客户组、Website 和优先级,减少同时有效的规则集合。不要用“全部网站、全部客户组”作为方便的默认值。
可从数据库查看基础范围,但 conditions 是序列化结构,修改应通过服务层和后台完成:
SELECT rule_id, name, is_active, from_date, to_date,
sort_order, stop_rules_processing
FROM salesrule
WHERE is_active=1
ORDER BY sort_order, rule_id;
Conditions 树越深,逐行验证越昂贵
大量嵌套 ALL/ANY、分类、SKU、属性、购物车金额和地址条件会触发不同数据加载。Actions 区域的商品条件还会对每个 Quote Item 验证。能在顶层快速排除的 Website、客户组、日期条件应由规则范围承担,不要全部塞进复杂树。
用于规则的商品属性必须配置为可用于促销规则并被正确索引。自定义 condition 如果每次验证都加载完整 Product 或远程 API,会形成 N×M 查询,应批量预取或缓存当前请求内结果。
规则优先级和停止后续规则处理能减少工作,但要符合业务
高优先级互斥规则在命中后可停止后续处理,减少验证,也避免优惠叠加。但不能为了性能随意开启,否则订单金额会改变。先建立规则组合测试,再调整。
索引不是所有规则性能问题的答案
目录价格规则有专门索引,购物车价格规则更多在 Quote totals 阶段动态计算。看到优惠慢就全量 reindex 往往无效。应通过 profiler/APM 找出具体 validator、SQL 和调用次数。
优化后用 1 行、20 行和含可配置/Bundle 的购物车测试,覆盖访客、不同客户组、有效和无效优惠码。比较 P95 响应时间与最终折扣明细,确保性能提升没有改变规则结果。

