生产环境Apex出现System.QueryException非选择性查询异常求助
Salesforce生产环境查询异常排查求助
遇到的异常
System.QueryException: Non-selective query against large object type (more than 1000000 rows). Consider an indexed filter...
触发异常的查询代码(位于触发器处理类)
for (Order_Line_Item__c oli : [SELECT id, Product_Code__c, Stock_Location__c, Contract_Product__r.Product__c FROM Order_Line_Item__c WHERE Contract_Product__c IN :cpIDSet AND Stock_Location__c IN :stockLocationSet AND Status__c = 'Open'])
已尝试的排查方案
- 使用索引筛选器提升查询选择性
- 确认查询返回记录数未超出Salesforce governor limits
- 排查查找数据倾斜问题,确认每个对象的查找数远低于10000
咨询问题
- 是否存在明显的问题点?
- 如何进一步提升该查询的选择性?
- 还有哪些额外的思路或方法可以尝试解决此问题?
异常截图

问题分析与解决方案
1. 明显的问题点
- 核心问题是查询选择性不足:尽管尝试了索引筛选,但当前过滤条件组合可能无法让Salesforce优化器有效利用索引。尤其当
Order_Line_Item__c数据量超100万行时,即便返回记录少,查询扫描范围仍可能过大。 - 需重点确认:
Contract_Product__c、Stock_Location__c、Status__c是否都有有效索引?若Status__c是无自定义索引的文本字段,会拉低整体选择性;另外,若cpIDSet或stockLocationSet包含ID过多(如超200个),IN子句的选择性也会下降。
2. 进一步提升查询选择性的方法
- 优化索引配置:
- 给
Status__c创建自定义索引,或结合Contract_Product__c/Stock_Location__c创建复合索引,尤其是当Status__c可选值较少时。 - 检查查找字段的空值占比:若
Contract_Product__c或Stock_Location__c存在大量空值,可在查询中添加!= null过滤,提升索引利用率。
- 给
- 缩小过滤范围:
- 限制
cpIDSet和stockLocationSet的大小,避免一次性传入过多ID,必要时拆分查询分批处理。 - 增加高选择性的额外过滤条件,比如按
CreatedDate或LastModifiedDate做范围筛选,进一步缩小扫描范围。
- 限制
- 验证查询计划:
- 使用Salesforce查询计划工具(Query Plan)分析该查询,查看实际命中的索引和扫描行数,确认是否存在索引未被有效利用的情况。
3. 额外思路与方法
- 分批处理查询:将大集合拆分为小批次(如每次处理100个ID),分批执行查询,降低单次查询的扫描范围。
- 利用平台缓存:若查询结果短时间内无频繁变化,可将结果存入Platform Cache,避免重复执行相同查询。
- 检查数据分布:统计
Status__c = 'Open'的记录占总数据量的比例,若占比超30%,即便有索引,Salesforce也可能选择全表扫描,此时需结合其他高选择性字段共同过滤。 - 异步化处理:若触发器同步执行压力大,可将该查询逻辑移至Queueable Apex等异步处理流程,减少同步执行时的资源占用。
内容的提问来源于stack exchange,提问作者Dprog
相关产品推荐
相关产品推荐

