Salesforce:在选择性查询上获取“非选择性查询”错误

时间:2014-05-14 13:59:01

标签: salesforce soql

我正在运行一个非常简单的SOQL查询,我已将其重命名为对象并包含在此处:

List <ObjectA__c> allRecords= [
select name, Id,Contact__c,...
from ObjectA__c
where Contact__c IN 
(SELECT Contact__c FROM ObjectB__c WHERE id IN :idList) 
];

ObjectB只有300条记录,objectA有超过200k的记录,所以显然是导致问题的对象。

显然,

id被索引,而objectB的联系人字段是一个主要的细节,所以它也被索引,并且不能包含空值。

我愿意接受任何有用的建议。故障排除只在导入中产生了这个错误(其中idList是建立在trigger.new之上)并且在aon apex中手动运行代码运行正常而没有问题。

我已经没有“尝试的东西”,所以欢迎提出建议。

2 个答案:

答案 0 :(得分:2)

除了眼睛的建议,你可以尝试新的Query Resource Feedback Parameter pilot。这将向您展示Salesforce如何在不实际运行查询的情况下执行查询。

链接文章有一个Visualforce页面和相关的Apex Controller,您可以使用它来形成这些REST查询。或者您可以使用FuseIT SFDC Explorer获取相同的信息(披露,我目前正在为FuseIT工作。这是开发人员的免费工具)。

SOQL Query Execution Plan

答案 1 :(得分:1)

我喜欢那些在没有评论他们认为可以改进的情况下投票问题的人......

一些一般阅读材料:


一般来说 - 您应该考虑这样一个事实:从长远来看,现在优化此查询可能会适得其反。如果使用了ObjectB的“正确”组合 - 您将达到50K查询行的限制,您的事务将回滚。更不用说用户手动插入带有“热门”联系人的记录将永远等待简单保存完成...夫妻想法:

  • 切成块并卸载到@future电话
  • 或提交可以更轻松处理此类工作量的批处理作业
  • 或减少导入的“batchSize”

在你的情况下 - 要么我没有正确地阅读这个问题,要么你过度复杂了。

  

(SELECT Contact__c FROM ObjectB__c WHERE id IN :idList)

     

idList是建立在trigger.new

之上的

加上我认为它发生在trigger somethingSomething on ObjectB__c(after insert)

您已在trigger.new中拥有所有ObjectB__c记录。没有必要查询它们&amp;他们的联系方式。

所以如果你收集所有联系人ID ...

Set<Id> contactIds = new Set<Id>();
for(ObjectB__c b : trigger.new){
    contactIds.add(b.Contact__c);
}
contactIds.remove(null);
System.debug(contactIds);

...您将能够编写简化的查询:

SELECT Id, Name, Contact__c
FROM ObjectA__c
WHERE Contact__c IN :contactIds

如果那个仍然会失败,你就无法过滤它们了。无法减少批量大小 - 是的,异步处理时间(@future或批处理作业)。