Quantcast
Channel: Microsoft Dynamics 365 Community
Viewing all 28716 articles
Browse latest View live

RetrieveMultiple Administrator Query

$
0
0

This post is part of a multi-part blog series regarding RetrieveMultiple performance.  To see a list of the other parts of this series, click here.

 

If you are a System Administrator, or have global access to the entity you are trying to query, the RetrieveMultiple statement does not need to take security into consideration.  In this scenario, the query is very straight forward.  Below is an example of this type of query for Activity records:

selecttop 51 "activitypointer0".Subjectas"subject"
,"activitypointer0".PriorityCode as"prioritycode"
,"activitypointer0".RegardingObjectId as"regardingobjectid"
,"activitypointer0".ActivityTypeCode as"activitytypecode"
,"activitypointer0".StateCode as"statecode"
,"activitypointer0".ScheduledStart as"scheduledstart"
,"activitypointer0".ScheduledEnd as"scheduledend"
,"activitypointer0".InstanceTypeCode as"instancetypecode"
,"activitypointer0".ActivityId as"activityid"
,"activitypointer0".RegardingObjectIdYomiName as"regardingobjectidyominame"
,"activitypointer0".RegardingObjectTypeCode as"regardingobjecttypecode"
,"activitypointer0".RegardingObjectIdName as"regardingobjectidname"
,"activitypointerowningusersystemusersystemuserid".InternalEMailAddress as"activitypointerowningusersystemusersystemuserid.internalemailaddress"
from
 ActivityPointeras"activitypointer0" WITH (NOLOCK)  leftouterjoinSystemUseras"activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = 1))orderby
 "activitypointer0".ScheduledEnd asc
,"activitypointer0".ActivityId asc

Tuning the Admin Query

One thing to keep in mind is that the basics of the above query are used in every RetrieveMultiple query, we simply inject the Security checks into it.  Thus, if the admin query is not performing optimally, non-admins are going to see similar performance problems.  Because of this, it is recommended to performance tune the admin query.
 
While SQL, as well as the Database Engine Tuning Advisory (DTA), may not provide a recommendation here for indexing, we can create an index that will improve the performance of the query.  The performance gain may not be immediately noticeable for admins if the query is already running fast, but once security is injected and more records need to be processed, the performance tuning done here will prove to be beneficial. 

Sample Index

 

The following index can be added here to cover the above query.  In my example test environment, this reduced the read count on ActivityPointerBase by 96%.
 
createnonclusteredindex [activityperftest] onActivityPointerBase
(ScheduledEnd,ActivityId,IsRegularActivity,OwnerId)
INCLUDE (Subject,PriorityCode,Regardingobjectid,activitytypecode,statecode,scheduledstart,instancetypecode,regardingobjectidyominame,regardingobjecttypecode,regardingobjectidname)
 
The method used to develop this index is as follows.  The indexed columns need to come from the Order By, Where, and Join items of the query, with the Order By coming first.  This is how the indexed columns were determined.  Next, any column in the view should be added as an Include column, unless it is already in the index as an indexed column. 
 
 Next post in this blog series: EnableRetrieveMultipleOptimization.

EnableRetrieveMultipleOptimization

$
0
0

This post is part of a multi-part blog series regarding RetrieveMultiple performance.  To see a list of the other parts of this series, click here.

 

The primary setting that is used to determine how to handle the security considerations of a RetrieveMultiple query for non-admin users is EnableRetrieveMultipleOptimization (ERMO).  The following are each of the applicable ERMO settings.  Please note in that almost all cases, setting ERMO to 0 will be the best option.

 

ERMO = 0

 

This should be the most commonly used setting for optimal performance.  This setting allows you to take advantage of the various sub-settings that will be discussed in upcoming posts.  We define this as the best setting to use when you have a wide variety of visibility counts between users, but in general it should be used in most situations.  One example of a query when ERMO is set to 0 is below, but please note that this is not all inclusive since various sub-settings can further alter the query here.
 
WITH"activitypointer0Security" as (
selectSubjectas"Subject",PriorityCodeas"PriorityCode",RegardingObjectIdas"RegardingObjectId",ActivityTypeCodeas"ActivityTypeCode",StateCodeas"StateCode",ScheduledStartas"ScheduledStart",ScheduledEndas"ScheduledEnd",InstanceTypeCodeas"InstanceTypeCode",ActivityIdas"ActivityId",RegardingObjectIdYomiNameas"RegardingObjectIdYomiName",RegardingObjectTypeCodeas"RegardingObjectTypeCode",RegardingObjectIdNameas"RegardingObjectIdName",IsRegularActivityas"IsRegularActivity",OwnerIdas"OwnerId",OwningBusinessUnitas"OwningBusinessUnit",OwningUseras"OwningUser" from [ActivityPointer] as"activitypointer0" where"activitypointer0".OwnerId in(SELECT id fromdbo.fn_GetGuidsFromString(@buIds0))
 
UNION
selectSubjectas"Subject",PriorityCodeas"PriorityCode",RegardingObjectIdas"RegardingObjectId",ActivityTypeCodeas"ActivityTypeCode",StateCodeas"StateCode",ScheduledStartas"ScheduledStart",ScheduledEndas"ScheduledEnd",InstanceTypeCodeas"InstanceTypeCode",ActivityIdas"ActivityId",RegardingObjectIdYomiNameas"RegardingObjectIdYomiName",RegardingObjectTypeCodeas"RegardingObjectTypeCode",RegardingObjectIdNameas"RegardingObjectIdName",IsRegularActivityas"IsRegularActivity",OwnerIdas"OwnerId",OwningBusinessUnitas"OwningBusinessUnit",OwningUseras"OwningUser" from [ActivityPointer] as"activitypointer0" where"activitypointer0".ActivityId in(selectPOA.ObjectIdfromPrincipalObjectAccess POA  WITH (NOLOCK)joinSystemUserPrincipals sup  WITH (NOLOCK)onPOA.PrincipalId=sup.PrincipalIdwheresup.SystemUserId= @SystemUserId00 andPOA.ObjectTypeCode= @ObjectTypeCode0 and((POA.AccessRightsMask|POA.InheritedAccessRightsMask)& 1)= 1)
UNION
selectSubjectas"Subject",PriorityCodeas"PriorityCode",RegardingObjectIdas"RegardingObjectId",ActivityTypeCodeas"ActivityTypeCode",StateCodeas"StateCode",ScheduledStartas"ScheduledStart",ScheduledEndas"ScheduledEnd",InstanceTypeCodeas"InstanceTypeCode",ActivityIdas"ActivityId",RegardingObjectIdYomiNameas"RegardingObjectIdYomiName",RegardingObjectTypeCodeas"RegardingObjectTypeCode",RegardingObjectIdNameas"RegardingObjectIdName",IsRegularActivityas"IsRegularActivity",OwnerIdas"OwnerId",OwningBusinessUnitas"OwningBusinessUnit",OwningUseras"OwningUser" from [ActivityPointer] as"activitypointer0" where"activitypointer0".OwningBusinessUnit in(@buId00)
 
)
select
top 51 "activitypointer0".Subjectas"subject"
,"activitypointer0".PriorityCode as"prioritycode"
,"activitypointer0".RegardingObjectId as"regardingobjectid"
,"activitypointer0".ActivityTypeCode as"activitytypecode"
,"activitypointer0".StateCode as"statecode"
,"activitypointer0".ScheduledStart as"scheduledstart"
,"activitypointer0".ScheduledEnd as"scheduledend"
,"activitypointer0".InstanceTypeCode as"instancetypecode"
,"activitypointer0".ActivityId as"activityid"
,"activitypointer0".RegardingObjectIdYomiName as"regardingobjectidyominame"
,"activitypointer0".RegardingObjectTypeCode as"regardingobjecttypecode"
,"activitypointer0".RegardingObjectIdName as"regardingobjectidname"
,"activitypointerowningusersystemusersystemuserid".InternalEMailAddress as"activitypointerowningusersystemusersystemuserid.internalemailaddress"
from
 activitypointer0Security as"activitypointer0" WITH (NOLOCK)  leftouterjoinSystemUseras"activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = @IsRegularActivity0))orderby
 "activitypointer0".ScheduledEnd asc
,"activitypointer0".ActivityId asc

ERMO = 1

This setting was considered the most optimal in CRM 4.0, as many of the additional settings we have today were not available.  Today we recommend considering this setting when all users have access restricted to just the data they own, and do not have any associated shares.  This would generally be a very uncommon scenario.
 
An example of a query when ERMO is set to 1 is below:
 
createtable #ObjectsIds(ObjectIduniqueidentifier);
createNONCLUSTEREDindexndx_ObjectsIds_objIdon #ObjectsIds(ObjectIdASC);
insertinto #ObjectsIds
selectPOA.ObjectIdfromPrincipalObjectAccess POA  WITH (NOLOCK)joinSystemUserPrincipals sup  WITH (NOLOCK)onPOA.PrincipalId=sup.PrincipalIdwheresup.SystemUserId= @SystemUserId0 andPOA.ObjectTypeCode= @ObjectTypeCodeand((POA.AccessRightsMask|POA.InheritedAccessRightsMask)& 1)= 1;
insertinto #ObjectsIds
selectActivityIdfrom [ActivityPointer]  WITH (NOLOCK)
whereOwnerIdin
(selectpem.PrincipalIdfromPrincipalEntityMappem  WITH (NOLOCK)joinSystemUserPrincipals sup  WITH (NOLOCK)onpem.PrincipalId=sup.PrincipalIdwheresup.SystemUserId= @UserIdOwnerCommand0 andpem.ObjectTypeCode= @OtcOwnerCommand0)
 
insertinto #ObjectsIds
selectActivityIdfrom [ActivityPointer]  WITH (NOLOCK)
whereowningbusinessunitin
(selectBusinessUnitIdfromSystemUserBusinessUnitEntityMapWITH (NOLOCK)whereSystemUserId= @SystemUserIdandObjectTypeCode= @ObjectTypeCode)
select
top 51 "activitypointer0".Subjectas"subject"
,"activitypointer0".PriorityCode as"prioritycode"
,"activitypointer0".RegardingObjectId as"regardingobjectid"
,"activitypointer0".ActivityTypeCode as"activitytypecode"
,"activitypointer0".StateCode as"statecode"
,"activitypointer0".ScheduledStart as"scheduledstart"
,"activitypointer0".ScheduledEnd as"scheduledend"
,"activitypointer0".InstanceTypeCode as"instancetypecode"
,"activitypointer0".ActivityId as"activityid"
,"activitypointer0".RegardingObjectIdYomiName as"regardingobjectidyominame"
,"activitypointer0".RegardingObjectTypeCode as"regardingobjecttypecode"
,"activitypointer0".RegardingObjectIdName as"regardingobjectidname"
,"activitypointerowningusersystemusersystemuserid".InternalEMailAddress as"activitypointerowningusersystemusersystemuserid.internalemailaddress"
from
 ActivityPointeras"activitypointer0" WITH (NOLOCK)  leftouterjoinSystemUseras"activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = @IsRegularActivity0)and("activitypointer0".ActivityId in(selectdistinctObjectIdfrom #ObjectsIds)))orderby
 "activitypointer0".ScheduledEnd asc
,"activitypointer0".ActivityId asc;
droptable #ObjectsIds 

ERMO = 2

This was considered the optimal setting in CRM 2011 pre-UR10.  This setting would be considered today when all users have visibility to a large amount of records, while being associated with a very small amount of Principals and Business Units.  This would be another edge scenario.
 
An example of a query when ERMO is set to 2 is below:
 
select
top 51 "activitypointer0".Subjectas"subject"
,"activitypointer0".PriorityCode as"prioritycode"
,"activitypointer0".RegardingObjectId as"regardingobjectid"
,"activitypointer0".ActivityTypeCode as"activitytypecode"
,"activitypointer0".StateCode as"statecode"
,"activitypointer0".ScheduledStart as"scheduledstart"
,"activitypointer0".ScheduledEnd as"scheduledend"
,"activitypointer0".InstanceTypeCode as"instancetypecode"
,"activitypointer0".ActivityId as"activityid"
,"activitypointer0".RegardingObjectIdYomiName as"regardingobjectidyominame"
,"activitypointer0".RegardingObjectTypeCode as"regardingobjecttypecode"
,"activitypointer0".RegardingObjectIdName as"regardingobjectidname"
,"activitypointerowningusersystemusersystemuserid".InternalEMailAddress as"activitypointerowningusersystemusersystemuserid.internalemailaddress"
from
 ActivityPointeras"activitypointer0" WITH (NOLOCK)  leftouterjoinSystemUseras"activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = @IsRegularActivity0)and("activitypointer0".OwnerId in(SELECT id fromdbo.fn_GetGuidsFromString(@buIds0))
 or"activitypointer0".ActivityId in(selectPOA.ObjectIdfromPrincipalObjectAccess POA
 WITH (NOLOCK)wherePOA.PrincipalIdin(@userPrincipalPOA00,@userPrincipalTeamPOA00,@userPrincipalTeamPOA1100,@userPrincipalTeamPOA2100,userPrincipalTeamPOA3100,@userPrincipalTeamPOA4100,@userPrincipalTeamPOA538,@userPrincipalTeamPOA610,@userPrincipalTeamPOA710,@userPrincipalTeamPOA810,@userPrincipalTeamPOA910,@userPrincipalTeamPOA1010,@userPrincipalTeamPOA1110,@userPrincipalTeamPOA1210,@userPrincipalTeamPOA1310,@userPrincipalTeamPOA1410,@userPrincipalTeamPOA1510,@userPrincipalTeamPOA1610,etc.etc.)andPOA.ObjectTypeCode= @ObjectTypeCode0 and((POA.AccessRightsMask|POA.InheritedAccessRightsMask)& 1)= 1)
 or"activitypointer0".OwningBusinessUnit in(@buId00)
))orderby
 "activitypointer0".ScheduledEnd asc
,"activitypointer0".ActivityId asc

ERMO = 3

This is a rarely used, and scarcely documented setting that is generally meant to be implemented only for performance and functional comparisons.  It would be considered optimal in environments where SQL memory is concerning, and all table row counts are small.
 
An example of a query when ERMO is set to 3 is below:
 
select
top 51 "activitypointer0".Subjectas"subject"
,"activitypointer0".PriorityCode as"prioritycode"
,"activitypointer0".RegardingObjectId as"regardingobjectid"
,"activitypointer0".ActivityTypeCode as"activitytypecode"
,"activitypointer0".StateCode as"statecode"
,"activitypointer0".ScheduledStart as"scheduledstart"
,"activitypointer0".ScheduledEnd as"scheduledend"
,"activitypointer0".InstanceTypeCode as"instancetypecode"
,"activitypointer0".ActivityId as"activityid"
,"activitypointer0".RegardingObjectIdYomiName as"regardingobjectidyominame"
,"activitypointer0".RegardingObjectTypeCode as"regardingobjecttypecode"
,"activitypointer0".RegardingObjectIdName as"regardingobjectidname"
,"activitypointerowningusersystemusersystemuserid".InternalEMailAddress as"activitypointerowningusersystemusersystemuserid.internalemailaddress"
from
 ActivityPointeras"activitypointer0" WITH (NOLOCK)  leftouterjoinSystemUseras"activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = @IsRegularActivity0)and("activitypointer0".OwnerId in(selectpem.PrincipalIdfromPrincipalEntityMappem  WITH (NOLOCK)joinSystemUserPrincipals sup  WITH (NOLOCK)onpem.PrincipalId=sup.PrincipalIdwheresup.SystemUserId= @UserIdOwnerCommand00 andpem.ObjectTypeCode= @OtcOwnerCommand00)
 or"activitypointer0".ActivityId in(selectPOA.ObjectIdfromPrincipalObjectAccess POA  WITH (NOLOCK)joinSystemUserPrincipals sup  WITH (NOLOCK)onPOA.PrincipalId=sup.PrincipalIdwheresup.SystemUserId= @SystemUserId00 andPOA.ObjectTypeCode= @ObjectTypeCode0 and((POA.AccessRightsMask|POA.InheritedAccessRightsMask)& 1)= 1)or"activitypointer0".OwningBusinessUnit in(selectBusinessUnitIdfromSystemUserBusinessUnitEntityMapWITH (NOLOCK)whereSystemUserId= @SystemUserId0 andObjectTypeCode= @ObjectTypeCode1)))orderby
 "activitypointer0".ScheduledEnd asc
,"activitypointer0".ActivityId asc
 
 Next post in this blog series: RecordCountLimitToSwitchToCteSecuritySql.

RecordCountLimitToSwitchToCteSecuritySql

$
0
0

This post is part of a multi-part blog series regarding RetrieveMultiple performance.  To see a list of the other parts of this series, click here.

 

This setting is what is used to determine at which point a CTE query should be executed for RetrieveMultiple.  The default value for this setting is 75,000, and can be modified via OrgDbOrgSettings.  If the entity’s record count is above the value for this setting, a CTE query will be executed.  If the entity’s record count is below the value for this setting, an OR-based query using joins will be used instead.

 
The entity’s record count is determined by retrieving the value from the RecordCountSnapshot table.  This table is updated daily by Maintenance Job 45 (RefreshRowCountSnapshots).  A helpful query that can be manually executed to review the Record Count sizes of every entity is below:
selecta.count,b.namefromRecordCountSnapshot a
join entity b ona.objecttypecode=b.ObjectTypeCode
orderbya.countdesc
Query examples of what you can expect to see from a CTE query and an or-based join query are below:

CTE Query

WITH"activitypointer0Security" as (
selectSubjectas"Subject",PriorityCodeas"PriorityCode",RegardingObjectIdas"RegardingObjectId",ActivityTypeCodeas"ActivityTypeCode",StateCodeas"StateCode",ScheduledStartas"ScheduledStart",ScheduledEndas"ScheduledEnd",InstanceTypeCodeas"InstanceTypeCode",ActivityIdas"ActivityId",RegardingObjectIdYomiNameas"RegardingObjectIdYomiName",RegardingObjectTypeCodeas"RegardingObjectTypeCode",RegardingObjectIdNameas"RegardingObjectIdName",IsRegularActivityas"IsRegularActivity",OwnerIdas"OwnerId",OwningBusinessUnitas"OwningBusinessUnit",OwningUseras"OwningUser" from [ActivityPointer] as"activitypointer0" where"activitypointer0".OwnerId in(SELECT id fromdbo.fn_GetGuidsFromString(@buIds0))
 
UNION
selectSubjectas"Subject",PriorityCodeas"PriorityCode",RegardingObjectIdas"RegardingObjectId",ActivityTypeCodeas"ActivityTypeCode",StateCodeas"StateCode",ScheduledStartas"ScheduledStart",ScheduledEndas"ScheduledEnd",InstanceTypeCodeas"InstanceTypeCode",ActivityIdas"ActivityId",RegardingObjectIdYomiNameas"RegardingObjectIdYomiName",RegardingObjectTypeCodeas"RegardingObjectTypeCode",RegardingObjectIdNameas"RegardingObjectIdName",IsRegularActivityas"IsRegularActivity",OwnerIdas"OwnerId",OwningBusinessUnitas"OwningBusinessUnit",OwningUseras"OwningUser" from [ActivityPointer] as"activitypointer0" where"activitypointer0".ActivityId in(selectPOA.ObjectIdfromPrincipalObjectAccess POA  WITH (NOLOCK)joinSystemUserPrincipals sup  WITH (NOLOCK)onPOA.PrincipalId=sup.PrincipalIdwheresup.SystemUserId= @SystemUserId00 andPOA.ObjectTypeCode= @ObjectTypeCode0 and((POA.AccessRightsMask|POA.InheritedAccessRightsMask)& 1)= 1)
UNION
selectSubjectas"Subject",PriorityCodeas"PriorityCode",RegardingObjectIdas"RegardingObjectId",ActivityTypeCodeas"ActivityTypeCode",StateCodeas"StateCode",ScheduledStartas"ScheduledStart",ScheduledEndas"ScheduledEnd",InstanceTypeCodeas"InstanceTypeCode",ActivityIdas"ActivityId",RegardingObjectIdYomiNameas"RegardingObjectIdYomiName",RegardingObjectTypeCodeas"RegardingObjectTypeCode",RegardingObjectIdNameas"RegardingObjectIdName",IsRegularActivityas"IsRegularActivity",OwnerIdas"OwnerId",OwningBusinessUnitas"OwningBusinessUnit",OwningUseras"OwningUser" from [ActivityPointer] as"activitypointer0" where"activitypointer0".OwningBusinessUnit in(@buId00)
 
)
select
top 51 "activitypointer0".Subjectas"subject"
,"activitypointer0".PriorityCode as"prioritycode"
,"activitypointer0".RegardingObjectId as"regardingobjectid"
,"activitypointer0".ActivityTypeCode as"activitytypecode"
,"activitypointer0".StateCode as"statecode"
,"activitypointer0".ScheduledStart as"scheduledstart"
,"activitypointer0".ScheduledEnd as"scheduledend"
,"activitypointer0".InstanceTypeCode as"instancetypecode"
,"activitypointer0".ActivityId as"activityid"
,"activitypointer0".RegardingObjectIdYomiName as"regardingobjectidyominame"
,"activitypointer0".RegardingObjectTypeCode as"regardingobjecttypecode"
,"activitypointer0".RegardingObjectIdName as"regardingobjectidname"
,"activitypointerowningusersystemusersystemuserid".InternalEMailAddress as"activitypointerowningusersystemusersystemuserid.internalemailaddress"
from
 activitypointer0Security as"activitypointer0" WITH (NOLOCK)  leftouterjoinSystemUseras"activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = @IsRegularActivity0))orderby
 "activitypointer0".ScheduledEnd asc
,"activitypointer0".ActivityId asc

OR-Based Query Using Joins

execsp_executesqlN'select
top 51 "activitypointer0".Subject as "subject"
, "activitypointer0".PriorityCode as "prioritycode"
, "activitypointer0".RegardingObjectId as "regardingobjectid"
, "activitypointer0".ActivityTypeCode as "activitytypecode"
, "activitypointer0".StateCode as "statecode"
, "activitypointer0".ScheduledStart as "scheduledstart"
, "activitypointer0".ScheduledEnd as "scheduledend"
, "activitypointer0".InstanceTypeCode as "instancetypecode"
, "activitypointer0".ActivityId as "activityid"
, "activitypointer0".RegardingObjectIdYomiName as "regardingobjectidyominame"
, "activitypointer0".RegardingObjectTypeCode as "regardingobjecttypecode"
, "activitypointer0".RegardingObjectIdName as "regardingobjectidname"
, "activitypointerowningusersystemusersystemuserid".InternalEMailAddress as "activitypointerowningusersystemusersystemuserid.internalemailaddress"
from
 ActivityPointer as "activitypointer0" WITH (NOLOCK)  left outer join SystemUser as "activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = @IsRegularActivity0) and ("activitypointer0".OwnerId in (select pem.PrincipalId from PrincipalEntityMappem  WITH (NOLOCK) join SystemUserPrincipals sup  WITH (NOLOCK) on pem.PrincipalId = sup.PrincipalId where sup.SystemUserId = @UserIdOwnerCommand00 and pem.ObjectTypeCode = @OtcOwnerCommand00)
 or "activitypointer0".ActivityId in (select POA.ObjectId from PrincipalObjectAccess POA  WITH (NOLOCK) join SystemUserPrincipals sup  WITH (NOLOCK) on POA.PrincipalId = sup.PrincipalId where sup.SystemUserId = @SystemUserId00 and POA.ObjectTypeCode = @ObjectTypeCode0 and ((POA.AccessRightsMask|POA.InheritedAccessRightsMask) & 1) = 1) or "activitypointer0".OwningBusinessUnit in (select BusinessUnitId from SystemUserBusinessUnitEntityMap WITH (NOLOCK) where SystemUserId = @SystemUserId0 and ObjectTypeCode = @ObjectTypeCode1))) order by
 "activitypointer0".ScheduledEnd asc
, "activitypointer0".ActivityId asc',N'@IsRegularActivity0 bit,@UserIdOwnerCommand00 uniqueidentifier,@OtcOwnerCommand00 int,@SystemUserId00 uniqueidentifier,@ObjectTypeCode0 int,@SystemUserId0 uniqueidentifier,@ObjectTypeCode1 int',@IsRegularActivity0=1,@UserIdOwnerCommand00='10762A09-58F6-E311-B866-6C3BE5A80FD8',@OtcOwnerCommand00=4200,@SystemUserId00='10762A09-58F6-E311-B866-6C3BE5A80FD8',@ObjectTypeCode0=4200,@SystemUserId0='10762A09-58F6-E311-B866-6C3BE5A80FD8',@ObjectTypeCode1=4200
 

Next post in this blog series: Sharing Considerations

Sharing Considerations

$
0
0

This post is part of a multi-part blog series regarding RetrieveMultiple performance.  To see a list of the other parts of this series, click here.

The RetrieveMultipleSharingCountThreshold setting is what we use to determine at which point we should utilize a Table Valued Function (TVF) to calculate sharing.  The default value for this setting is 1000, and can be modified via OrgDbOrgSettings.  If the user’s share count is below the value for this setting, we will use TVF to calculate sharing.
 
A user’s share count is determined by retrieving the value from the PrincipalObjectAccessReadSnapshot table.  The user’s share count is broken down by entity in this table.  The table is updated daily by Maintenance Job 46 (RefreshReadSharingSnapshots).  A helpful query that can be manually executed to review the Record Count sizes for every user and every entity is below:
selectb.FullName,a.Count,c.NameasEntityNamefromPrincipalObjectAccessReadSnapshot a
joinsystemuserbase b ona.principalid=b.systemuserid
join entity c ona.ObjectTypeCode=c.ObjectTypeCode
orderbyb.FullNameasc,a.Countdesc
Query examples are below, with the highlighted portion illustrating the differences based on which setting is used:

Query Below RetreiveMultipleSharingCountThreshold Value

execsp_executesqlN'WITH "activitypointer0Security" as (
select Subject as "Subject", PriorityCode as "PriorityCode", RegardingObjectId as "RegardingObjectId", ActivityTypeCode as "ActivityTypeCode", StateCode as "StateCode", ScheduledStart as "ScheduledStart", ScheduledEnd as "ScheduledEnd", InstanceTypeCode as "InstanceTypeCode", ActivityId as "ActivityId", RegardingObjectIdYomiName as "RegardingObjectIdYomiName", RegardingObjectTypeCode as "RegardingObjectTypeCode", RegardingObjectIdName as "RegardingObjectIdName", IsRegularActivity as "IsRegularActivity", OwnerId as "OwnerId", OwningBusinessUnit as "OwningBusinessUnit", OwningUser as "OwningUser" from [ActivityPointer] as "activitypointer0" where "activitypointer0".OwnerId in (SELECT id from dbo.fn_GetGuidsFromString(@buIds0))
 
UNION
select Subject as "Subject", PriorityCode as "PriorityCode", RegardingObjectId as "RegardingObjectId", ActivityTypeCode as "ActivityTypeCode", StateCode as "StateCode", ScheduledStart as "ScheduledStart", ScheduledEnd as "ScheduledEnd", InstanceTypeCode as "InstanceTypeCode", ActivityId as "ActivityId", RegardingObjectIdYomiName as "RegardingObjectIdYomiName", RegardingObjectTypeCode as "RegardingObjectTypeCode", RegardingObjectIdName as "RegardingObjectIdName", IsRegularActivity as "IsRegularActivity", OwnerId as "OwnerId", OwningBusinessUnit as "OwningBusinessUnit", OwningUser as "OwningUser" from [ActivityPointer] as "activitypointer0" where "activitypointer0".ActivityId in (select ObjectId from fn_POARetrieveMultiple(@SystemUserId0, @ObjectTypeCode0,@isHierarchicalSecurityModelEnabled0))
UNION
select Subject as "Subject", PriorityCode as "PriorityCode", RegardingObjectId as "RegardingObjectId", ActivityTypeCode as "ActivityTypeCode", StateCode as "StateCode", ScheduledStart as "ScheduledStart", ScheduledEnd as "ScheduledEnd", InstanceTypeCode as "InstanceTypeCode", ActivityId as "ActivityId", RegardingObjectIdYomiName as "RegardingObjectIdYomiName", RegardingObjectTypeCode as "RegardingObjectTypeCode", RegardingObjectIdName as "RegardingObjectIdName", IsRegularActivity as "IsRegularActivity", OwnerId as "OwnerId", OwningBusinessUnit as "OwningBusinessUnit", OwningUser as "OwningUser" from [ActivityPointer] as "activitypointer0" where "activitypointer0".OwningBusinessUnit in (@buId00)
 
)
select
top 51 "activitypointer0".Subject as "subject"
, "activitypointer0".PriorityCode as "prioritycode"
, "activitypointer0".RegardingObjectId as "regardingobjectid"
, "activitypointer0".ActivityTypeCode as "activitytypecode"
, "activitypointer0".StateCode as "statecode"
, "activitypointer0".ScheduledStart as "scheduledstart"
, "activitypointer0".ScheduledEnd as "scheduledend"
, "activitypointer0".InstanceTypeCode as "instancetypecode"
, "activitypointer0".ActivityId as "activityid"
, "activitypointer0".RegardingObjectIdYomiName as "regardingobjectidyominame"
, "activitypointer0".RegardingObjectTypeCode as "regardingobjecttypecode"
, "activitypointer0".RegardingObjectIdName as "regardingobjectidname"
, "activitypointerowningusersystemusersystemuserid".InternalEMailAddress as "activitypointerowningusersystemusersystemuserid.internalemailaddress"
from
 activitypointer0Security as "activitypointer0" WITH (NOLOCK)  left outer join SystemUser as "activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = @IsRegularActivity0)) order by
 "activitypointer0".ScheduledEnd asc
, "activitypointer0".ActivityId asc'

Query Above RetreiveMultipleSharingCountThreshold Value

WITH"activitypointer0Security" as (
selectSubjectas"Subject",PriorityCodeas"PriorityCode",RegardingObjectIdas"RegardingObjectId",ActivityTypeCodeas"ActivityTypeCode",StateCodeas"StateCode",ScheduledStartas"ScheduledStart",ScheduledEndas"ScheduledEnd",InstanceTypeCodeas"InstanceTypeCode",ActivityIdas"ActivityId",RegardingObjectIdYomiNameas"RegardingObjectIdYomiName",RegardingObjectTypeCodeas"RegardingObjectTypeCode",RegardingObjectIdNameas"RegardingObjectIdName",IsRegularActivityas"IsRegularActivity",OwnerIdas"OwnerId",OwningBusinessUnitas"OwningBusinessUnit",OwningUseras"OwningUser" from [ActivityPointer] as"activitypointer0" where"activitypointer0".OwnerId in(SELECT id fromdbo.fn_GetGuidsFromString(@buIds0))
 
UNION
selectSubjectas"Subject",PriorityCodeas"PriorityCode",RegardingObjectIdas"RegardingObjectId",ActivityTypeCodeas"ActivityTypeCode",StateCodeas"StateCode",ScheduledStartas"ScheduledStart",ScheduledEndas"ScheduledEnd",InstanceTypeCodeas"InstanceTypeCode",ActivityIdas"ActivityId",RegardingObjectIdYomiNameas"RegardingObjectIdYomiName",RegardingObjectTypeCodeas"RegardingObjectTypeCode",RegardingObjectIdNameas"RegardingObjectIdName",IsRegularActivityas"IsRegularActivity",OwnerIdas"OwnerId",OwningBusinessUnitas"OwningBusinessUnit",OwningUseras"OwningUser" from [ActivityPointer] as"activitypointer0" where"activitypointer0".ActivityId in(selectPOA.ObjectIdfromPrincipalObjectAccess POA  WITH (NOLOCK)joinSystemUserPrincipals sup  WITH (NOLOCK)onPOA.PrincipalId=sup.PrincipalIdwheresup.SystemUserId= @SystemUserId00 andPOA.ObjectTypeCode= @ObjectTypeCode0 and((POA.AccessRightsMask|POA.InheritedAccessRightsMask)& 1)= 1)
UNION
selectSubjectas"Subject",PriorityCodeas"PriorityCode",RegardingObjectIdas"RegardingObjectId",ActivityTypeCodeas"ActivityTypeCode",StateCodeas"StateCode",ScheduledStartas"ScheduledStart",ScheduledEndas"ScheduledEnd",InstanceTypeCodeas"InstanceTypeCode",ActivityIdas"ActivityId",RegardingObjectIdYomiNameas"RegardingObjectIdYomiName",RegardingObjectTypeCodeas"RegardingObjectTypeCode",RegardingObjectIdNameas"RegardingObjectIdName",IsRegularActivityas"IsRegularActivity",OwnerIdas"OwnerId",OwningBusinessUnitas"OwningBusinessUnit",OwningUseras"OwningUser" from [ActivityPointer] as"activitypointer0" where"activitypointer0".OwningBusinessUnit in(@buId00)
 
)
select
top 51 "activitypointer0".Subjectas"subject"
,"activitypointer0".PriorityCode as"prioritycode"
,"activitypointer0".RegardingObjectId as"regardingobjectid"
,"activitypointer0".ActivityTypeCode as"activitytypecode"
,"activitypointer0".StateCode as"statecode"
,"activitypointer0".ScheduledStart as"scheduledstart"
,"activitypointer0".ScheduledEnd as"scheduledend"
,"activitypointer0".InstanceTypeCode as"instancetypecode"
,"activitypointer0".ActivityId as"activityid"
,"activitypointer0".RegardingObjectIdYomiName as"regardingobjectidyominame"
,"activitypointer0".RegardingObjectTypeCode as"regardingobjecttypecode"
,"activitypointer0".RegardingObjectIdName as"regardingobjectidname"
,"activitypointerowningusersystemusersystemuserid".InternalEMailAddress as"activitypointerowningusersystemusersystemuserid.internalemailaddress"
from
 activitypointer0Security as"activitypointer0" WITH (NOLOCK)  leftouterjoinSystemUseras"activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = @IsRegularActivity0))orderby
 "activitypointer0".ScheduledEnd asc
,"activitypointer0".ActivityId asc
 
 
 

SharingLimitForSnapshotTable Note


This setting determines the threshold in which a Principal/ObjectTypeCode entry should be created in the PrincipalObjectAccessReadSnapshot table.  The default value for this setting is 10, and it can be modified via OrgDbOrgSettings.  This value should be increased for customers that have users who are members of a large number of teams, and each team has a small amount of records shared.  The setting increase would allow CRM to better handle this scenario, and better detect whether or not TVF should be used.

 
 
Next post in this blog series: IdsCount* Settings

IdsCount* Settings

$
0
0

This post is part of a multi-part blog series regarding RetrieveMultiple performance.  To see a list of the other parts of this series, click here.

These settings are what is used to determine how to format our security clause.  There are three methods that can be used for the security clause based on these settings:  Inline IDs, TVF, or Joins.  Descriptions of the settings used to make this determination are below, along with query examples.  In the query examples, the highlighted portion illustrates the differences made by each setting change.
 

IdsCountForUsingGuidStringForSecurity

 
This is the setting that determines whether we use Inline IDs, or pass the IDs as a string and parse the string using TVF to create an in-memory table of IDs.  The default value for this setting is 20, and can be modified via OrgDbOrgSettings.  This setting cannot be set to a higher value than IdsCountBeforeUsingJoinsForSecurity.
 

IdsCountBeforeUsingJoinsForSecurity

 
This is the setting that determines at what point we no longer use TVF as defined by the above setting, and instead use joins against the different security tables rather than passing IDs to SQL.  The default value for this setting is 1000, and can be modified via OrgDbOrgSettings.  This value cannot be set to a lower setting than IdsCountForUsingGuidStringForSecurity.
  

Query Below IdsCountForUsingGuidStringForSecurity

execsp_executesqlN'WITH "activitypointer0Security" as (
select Subject as "Subject", PriorityCode as "PriorityCode", RegardingObjectId as "RegardingObjectId", ActivityTypeCode as "ActivityTypeCode", StateCode as "StateCode", ScheduledStart as "ScheduledStart", ScheduledEnd as "ScheduledEnd", InstanceTypeCode as "InstanceTypeCode", ActivityId as "ActivityId", RegardingObjectIdYomiName as "RegardingObjectIdYomiName", RegardingObjectTypeCode as "RegardingObjectTypeCode", RegardingObjectIdName as "RegardingObjectIdName", IsRegularActivity as "IsRegularActivity", OwnerId as "OwnerId", OwningBusinessUnit as "OwningBusinessUnit", OwningUser as "OwningUser" from [ActivityPointer] as "activitypointer0" where ("activitypointer0".OwnerId in (@userPrincipalWithBasicDepth00,@userPrincipalWithBasicDepth1100,@userPrincipalWithBasicDepth2100,@userPrincipalWithBasicDepth3100,@userPrincipalWithBasicDepth4100,@userPrincipalWithBasicDepth537,@userPrincipalWithBasicDepth5360,etc.etc)
 or "activitypointer0".OwningBusinessUnit in (@buId00)
)
UNION
select Subject as "Subject", PriorityCode as "PriorityCode", RegardingObjectId as "RegardingObjectId", ActivityTypeCode as "ActivityTypeCode", StateCode as "StateCode", ScheduledStart as "ScheduledStart", ScheduledEnd as "ScheduledEnd", InstanceTypeCode as "InstanceTypeCode", ActivityId as "ActivityId", RegardingObjectIdYomiName as "RegardingObjectIdYomiName", RegardingObjectTypeCode as "RegardingObjectTypeCode", RegardingObjectIdName as "RegardingObjectIdName", IsRegularActivity as "IsRegularActivity", OwnerId as "OwnerId", OwningBusinessUnit as "OwningBusinessUnit", OwningUser as "OwningUser" from [ActivityPointer] as "activitypointer0" where ("activitypointer0".ActivityId in (select POA.ObjectId from PrincipalObjectAccess POA  WITH (NOLOCK) join SystemUserPrincipals sup  WITH (NOLOCK) on POA.PrincipalId = sup.PrincipalId where sup.SystemUserId = @SystemUserId00 and POA.ObjectTypeCode = @ObjectTypeCode0 and ((POA.AccessRightsMask|POA.InheritedAccessRightsMask) & 1) = 1))
)
select
top 51 "activitypointer0".Subject as "subject"
, "activitypointer0".PriorityCode as "prioritycode"
, "activitypointer0".RegardingObjectId as "regardingobjectid"
, "activitypointer0".ActivityTypeCode as "activitytypecode"
, "activitypointer0".StateCode as "statecode"
, "activitypointer0".ScheduledStart as "scheduledstart"
, "activitypointer0".ScheduledEnd as "scheduledend"
, "activitypointer0".InstanceTypeCode as "instancetypecode"
, "activitypointer0".ActivityId as "activityid"
, "activitypointer0".RegardingObjectIdYomiName as "regardingobjectidyominame"
, "activitypointer0".RegardingObjectTypeCode as "regardingobjecttypecode"
, "activitypointer0".RegardingObjectIdName as "regardingobjectidname"
, "activitypointerowningusersystemusersystemuserid".InternalEMailAddress as "activitypointerowningusersystemusersystemuserid.internalemailaddress"
from
 activitypointer0Security as "activitypointer0" WITH (NOLOCK)  left outer join SystemUser as "activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = @IsRegularActivity0)) order by
 "activitypointer0".ScheduledEnd asc

Query Above IdsCountForUsingGuidStringForSecurity, Below IdsCountBeforeUsingJoinsForSecurity

execsp_executesqlN'WITH "activitypointer0Security" as (
select Subject as "Subject", PriorityCode as "PriorityCode", RegardingObjectId as "RegardingObjectId", ActivityTypeCode as "ActivityTypeCode", StateCode as "StateCode", ScheduledStart as "ScheduledStart", ScheduledEnd as "ScheduledEnd", InstanceTypeCode as "InstanceTypeCode", ActivityId as "ActivityId", RegardingObjectIdYomiName as "RegardingObjectIdYomiName", RegardingObjectTypeCode as "RegardingObjectTypeCode", RegardingObjectIdName as "RegardingObjectIdName", IsRegularActivity as "IsRegularActivity", OwnerId as "OwnerId", OwningBusinessUnit as "OwningBusinessUnit", OwningUser as "OwningUser" from [ActivityPointer] as "activitypointer0" where "activitypointer0".OwnerId in (SELECT id from dbo.fn_GetGuidsFromString(@buIds0))
 
UNION
select Subject as "Subject", PriorityCode as "PriorityCode", RegardingObjectId as "RegardingObjectId", ActivityTypeCode as "ActivityTypeCode", StateCode as "StateCode", ScheduledStart as "ScheduledStart", ScheduledEnd as "ScheduledEnd", InstanceTypeCode as "InstanceTypeCode", ActivityId as "ActivityId", RegardingObjectIdYomiName as "RegardingObjectIdYomiName", RegardingObjectTypeCode as "RegardingObjectTypeCode", RegardingObjectIdName as "RegardingObjectIdName", IsRegularActivity as "IsRegularActivity", OwnerId as "OwnerId", OwningBusinessUnit as "OwningBusinessUnit", OwningUser as "OwningUser" from [ActivityPointer] as "activitypointer0" where "activitypointer0".ActivityId in (select POA.ObjectId from PrincipalObjectAccess POA  WITH (NOLOCK) join SystemUserPrincipals sup  WITH (NOLOCK) on POA.PrincipalId = sup.PrincipalId where sup.SystemUserId = @SystemUserId00 and POA.ObjectTypeCode = @ObjectTypeCode0 and ((POA.AccessRightsMask|POA.InheritedAccessRightsMask) & 1) = 1)
UNION
select Subject as "Subject", PriorityCode as "PriorityCode", RegardingObjectId as "RegardingObjectId", ActivityTypeCode as "ActivityTypeCode", StateCode as "StateCode", ScheduledStart as "ScheduledStart", ScheduledEnd as "ScheduledEnd", InstanceTypeCode as "InstanceTypeCode", ActivityId as "ActivityId", RegardingObjectIdYomiName as "RegardingObjectIdYomiName", RegardingObjectTypeCode as "RegardingObjectTypeCode", RegardingObjectIdName as "RegardingObjectIdName", IsRegularActivity as "IsRegularActivity", OwnerId as "OwnerId", OwningBusinessUnit as "OwningBusinessUnit", OwningUser as "OwningUser" from [ActivityPointer] as "activitypointer0" where "activitypointer0".OwningBusinessUnit in (@buId00)
 
)
select
top 51 "activitypointer0".Subject as "subject"
, "activitypointer0".PriorityCode as "prioritycode"
, "activitypointer0".RegardingObjectId as "regardingobjectid"
, "activitypointer0".ActivityTypeCode as "activitytypecode"
, "activitypointer0".StateCode as "statecode"
, "activitypointer0".ScheduledStart as "scheduledstart"
, "activitypointer0".ScheduledEnd as "scheduledend"
, "activitypointer0".InstanceTypeCode as "instancetypecode"
, "activitypointer0".ActivityId as "activityid"
, "activitypointer0".RegardingObjectIdYomiName as "regardingobjectidyominame"
, "activitypointer0".RegardingObjectTypeCode as "regardingobjecttypecode"
, "activitypointer0".RegardingObjectIdName as "regardingobjectidname"
, "activitypointerowningusersystemusersystemuserid".InternalEMailAddress as "activitypointerowningusersystemusersystemuserid.internalemailaddress"
from
 activitypointer0Security as "activitypointer0" WITH (NOLOCK)  left outer join SystemUser as "activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = @IsRegularActivity0)) order by
 "activitypointer0".ScheduledEnd asc
, "activitypointer0".ActivityId asc

Query Above IdsCountForUsingJoinsForSecurity

execsp_executesqlN'WITH "activitypointer0Security" as (
select Subject as "Subject", PriorityCode as "PriorityCode", RegardingObjectId as "RegardingObjectId", ActivityTypeCode as "ActivityTypeCode", StateCode as "StateCode", ScheduledStart as "ScheduledStart", ScheduledEnd as "ScheduledEnd", InstanceTypeCode as "InstanceTypeCode", ActivityId as "ActivityId", RegardingObjectIdYomiName as "RegardingObjectIdYomiName", RegardingObjectTypeCode as "RegardingObjectTypeCode", RegardingObjectIdName as "RegardingObjectIdName", IsRegularActivity as "IsRegularActivity", OwnerId as "OwnerId", OwningBusinessUnit as "OwningBusinessUnit", OwningUser as "OwningUser" from [ActivityPointer] as "activitypointer0" where "activitypointer0".OwnerId in (select pem.PrincipalId from PrincipalEntityMap pem  WITH (NOLOCK) join SystemUserPrincipals sup  WITH (NOLOCK) on pem.PrincipalId = sup.PrincipalId where sup.SystemUserId = @UserIdOwnerCommand00 and pem.ObjectTypeCode = @OtcOwnerCommand00)
 
UNION
select Subject as "Subject", PriorityCode as "PriorityCode", RegardingObjectId as "RegardingObjectId", ActivityTypeCode as "ActivityTypeCode", StateCode as "StateCode", ScheduledStart as "ScheduledStart", ScheduledEnd as "ScheduledEnd", InstanceTypeCode as "InstanceTypeCode", ActivityId as "ActivityId", RegardingObjectIdYomiName as "RegardingObjectIdYomiName", RegardingObjectTypeCode as "RegardingObjectTypeCode", RegardingObjectIdName as "RegardingObjectIdName", IsRegularActivity as "IsRegularActivity", OwnerId as "OwnerId", OwningBusinessUnit as "OwningBusinessUnit", OwningUser as "OwningUser" from [ActivityPointer] as "activitypointer0" where "activitypointer0".ActivityId in (select POA.ObjectId from PrincipalObjectAccess POA  WITH (NOLOCK) join SystemUserPrincipals sup  WITH (NOLOCK) on POA.PrincipalId = sup.PrincipalId where sup.SystemUserId = @SystemUserId00 and POA.ObjectTypeCode = @ObjectTypeCode0 and ((POA.AccessRightsMask|POA.InheritedAccessRightsMask) & 1) = 1)
UNION
select Subject as "Subject", PriorityCode as "PriorityCode", RegardingObjectId as "RegardingObjectId", ActivityTypeCode as "ActivityTypeCode", StateCode as "StateCode", ScheduledStart as "ScheduledStart", ScheduledEnd as "ScheduledEnd", InstanceTypeCode as "InstanceTypeCode", ActivityId as "ActivityId", RegardingObjectIdYomiName as "RegardingObjectIdYomiName", RegardingObjectTypeCode as "RegardingObjectTypeCode", RegardingObjectIdName as "RegardingObjectIdName", IsRegularActivity as "IsRegularActivity", OwnerId as "OwnerId", OwningBusinessUnit as "OwningBusinessUnit", OwningUser as "OwningUser" from [ActivityPointer] as "activitypointer0" where "activitypointer0".OwningBusinessUnit in (@buId00)
 
)
select
top 51 "activitypointer0".Subject as "subject"
, "activitypointer0".PriorityCode as "prioritycode"
, "activitypointer0".RegardingObjectId as "regardingobjectid"
, "activitypointer0".ActivityTypeCode as "activitytypecode"
, "activitypointer0".StateCode as "statecode"
, "activitypointer0".ScheduledStart as "scheduledstart"
, "activitypointer0".ScheduledEnd as "scheduledend"
, "activitypointer0".InstanceTypeCode as "instancetypecode"
, "activitypointer0".ActivityId as "activityid"
, "activitypointer0".RegardingObjectIdYomiName as "regardingobjectidyominame"
, "activitypointer0".RegardingObjectTypeCode as "regardingobjecttypecode"
, "activitypointer0".RegardingObjectIdName as "regardingobjectidname"
, "activitypointerowningusersystemusersystemuserid".InternalEMailAddress as "activitypointerowningusersystemusersystemuserid.internalemailaddress"
from
 activitypointer0Security as "activitypointer0" WITH (NOLOCK)  left outer join SystemUser as "activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = @IsRegularActivity0)) order by
 "activitypointer0".ScheduledEnd asc
, "activitypointer0".ActivityId asc',N'@IsRegularActivity0 bit,@UserIdOwnerCommand00 uniqueidentifier,@OtcOwnerCommand00 int,@SystemUserId00 uniqueidentifier,@ObjectTypeCode0 int,@buId00 uniqueidentifier',@IsRegularActivity0=1,@UserIdOwnerCommand00='10762A09-58F6-E311-B866-6C3BE5A80FD8',@OtcOwnerCommand00=4200,@SystemUserId00='10762A09-58F6-E311-B866-6C3BE5A80FD8',@ObjectTypeCode0=4200,@buId00='6E9336D9-BDCF-E311-B03A-78E7D162CED1'
Next post in this blog series: Other Considerations

Other Considerations

$
0
0

This post is part of a multi-part blog series regarding RetrieveMultiple performance.  To see a list of the other parts of this series, click here.

 

TotalRecordCount Considerations

The TotalRecordCount query will also execute using the security considerations of RetrieveMultiple.  Both the TotalRecordCount and RetrieveMultiple query need to complete prior to data being displayed for the end user.  If the customer does not need the TotalRecordCount value to be displayed, it is recommended to disable it for performance reasons by setting SkipGettingRecordCountForPaging to True using OrgDbOrgSettings.


An example of a TotalRecordCount query is below:

WITH"activitypointer0Security" as (
selectActivityIdas"ActivityId",IsRegularActivityas"IsRegularActivity",OwnerIdas"OwnerId",OwningBusinessUnitas"OwningBusinessUnit",OwningUseras"OwningUser" from [ActivityPointer] as"activitypointer0" where"activitypointer0".OwnerId in(SELECT id fromdbo.fn_GetGuidsFromString(@buIds0))
 
UNION
selectActivityIdas"ActivityId",IsRegularActivityas"IsRegularActivity",OwnerIdas"OwnerId",OwningBusinessUnitas"OwningBusinessUnit",OwningUseras"OwningUser" from [ActivityPointer] as"activitypointer0" where"activitypointer0".ActivityId in(selectPOA.ObjectIdfromPrincipalObjectAccess POA  WITH (NOLOCK)joinSystemUserPrincipals sup  WITH (NOLOCK)onPOA.PrincipalId=sup.PrincipalIdwheresup.SystemUserId= @SystemUserId00 andPOA.ObjectTypeCode= @ObjectTypeCode0 and((POA.AccessRightsMask|POA.InheritedAccessRightsMask)& 1)= 1)
UNION
selectActivityIdas"ActivityId",IsRegularActivityas"IsRegularActivity",OwnerIdas"OwnerId",OwningBusinessUnitas"OwningBusinessUnit",OwningUseras"OwningUser" from [ActivityPointer] as"activitypointer0" where"activitypointer0".OwningBusinessUnit in(@buId00)
 
)
select
COUNT(*)as [#TotalRecordCount]
from
 (select
top 5001 "activitypointer0".ActivityId as"activityid"
,"activitypointerowningusersystemusersystemuserid".SystemUserIdas"activitypointerowningusersystemusersystemuserid.systemuserid"
from
 activitypointer0Security as"activitypointer0" WITH (NOLOCK)  leftouterjoinSystemUseras"activitypointerowningusersystemusersystemuserid" WITH (NOLOCK)  on ("activitypointer0".OwningUser  =  "activitypointerowningusersystemusersystemuserid".SystemUserId)
where
 (("activitypointer0".IsRegularActivity = @IsRegularActivity0)))as"#Subquery"

Other Considerations and Limitations

 

·       When a query is being executed offline, we will default to ERMO = 3.  Data is filtered when offline, so there isn’t a need for these optimizations.  Also, security is not a big consideration when offline, since you cannot take any data offline that you don’t have access to read anyway.  Additionally, the Shapshot tables are not taken offline.

 

·       Quick Find defaults to ERMO = 3.  The reason for this is that the quick find will be the most selective criteria, thus there is no need to add the overhead of a CTE query.

 

·       RetrieveMultiple settings are universal, so currently they cannot be set differently per entity.  This is being considered for a future release.

 
This is the last part of this blog series.

Few more interesting issues in New Form Rendering in CRM 2016 Update 1

$
0
0
We recently upgraded to CRM 2016 Update 1 and there seems to be noend to the different product issues that we are facing. The latest ones are missing scroll bar in BPF when a particular stage has large number of fields in it and the other one being...(read more)

The CRM Minute: Office 365 and Dynamics 365 – The New “Dynamic” Duo [VIDEO]

$
0
0
Office 365 and Dynamics 365

Office 365 and Dynamics 365 go together like peanut butter and jelly, which means that here at PowerObjects, we love talking about BOTH! In today’s episode of The CRM Minute, we’ll hear from Genya, our Office 365 superhero, on Office 365 and Dynamics 365 and the role they play with each other within the Microsoft ecosystem.

As you can see, you really do get more out of your CRM for Dynamics 365 platform by taking advantage of the features and functionality included within Office 365. To learn more about this topic, make sure to sign up for Genya’s webinar, and if you can’t make the webinar date and time, don’t sweat it! We record all of our webinars so that they are available on demand. Register for a webinar and we’ll send you the content after the event.

Happy CRM’ing!

Additional Resources


Microsoft.Crm.Setup.Server.RegisterVssWriterServiceAction error

$
0
0
Today I got this error during the installation of a Dynamics 365 Back-end server (Partly dutch) : 17:22:23|  Error| System.Exception: Actie Microsoft.Crm.Setup.Server.RegisterVssWriterServiceAction is...(read more)

Error of the Day: You need a Microsoft Dynamics CRM Online license to continue

$
0
0
I ran into a situation yesterday where a customer was seeing this very scary error message:     This is very odd, considering they were already logged into Dynamics CRM 2016 Online and everything was working – until it wasn’t. After a bit of digging around, I ran into this forum post, which outlined a […]

Team: Prescribed vs. Defined

$
0
0

I must be getting old for I am having more of the Carousel experiences of life. 

Take for instance that one of the benefits of getting older is that you get to walk into situations where you have been before. You have multiple similar experiences to draw from based on many other projects. It is a gift to clients, because some processes that are less efficient can be avoided and they get more cream of the crop (potentially).

So the thought of the day?

When defining user stories, gathering requirements, detailing out the current processes of the day. Think really, really hard about defining the specific issues, problems and current state without including the solution.

Ideally what you want is a team solution. A solution that pulls from the experiences of all members of the team. This is harder than it sounds, because it requires that each person really listens to and understands the full scope of the problem. It then requires that the team jointly agrees on the issue or problems and once agreed, solutioning can begin.

Solutioning will need to include the technical best choices and training among the team on the strengths and weakness as well as the business best choices.

Now in an ideal world this would all be done with any egos parked at the door, but rarely is this the reality. People have strong opinions. Humans are designed to compete or culturally trained to compete and thoughts outside of the comfort zones, make people uncomfortable. Mix in the awesome power of diversity and the energy can get very confused.

YET when this energy is aligned and diversity and multiple opinions come together as one. Amazing happens.

So keep stretching for Amazing  and keep learning, because the more we push ourselves to learn outside our comfort zones, the more we learn to listen and hear and the more we learn to share, the better the experiences will be!

Registration for the Dynamics 365/CRM JavaScript Development Workshop Ends Soon

$
0
0
Hi Everyone, I wanted to remind you that registration for next week’s Dynamics 365/CRM JavaScript Development workshop will end at 12:00pm CST on Monday, January 16th.. The goal of the class is for me to give you a very thorough introduction to using JavaScript within Dynamics CRM. When: This workshop will be held over a […]

10 FAQ’s from Service Professionals of Dynamics 365/CRM

$
0
0

faq-logo

Happy new year to you all! We hope everyone is off to a great start in 2017. We thought the new year would be a great time to share some of the top frequently asked questions our support team has received over the past year from service professionals who work with Dynamics 365/CRM. Below are the top ten most frequently asked questions about Dynamics 365 from service professionals in 2016.

1) Can you continue sharing a View created by someone who is no longer a User?

Yes, as long as you have the permission to share this View.

2) Can you use a NOT conditions when building Advanced Find queries?

Yes. For example, you can see all Accounts not owned by a specific User.

3) Can you use Advanced Find to query for records not created during a certain time period?

Yes. To do this, you should query for records created before the beginning of that time period OR records created after the end of that time period. That will give you the result that you are looking for.

4) How can I create a dashboard with more than 6 Charts?

To do this, you will have to use iFrames to embed Dashboards within Dashboards. Click here to see our blog post on this topic.

5) How do I know the difference between My Views and System Views?

  • System Views
    • Available to everyone and do not need to be shared
    • Can only be changed in the Customization and Configuration Section
    • Created by an Administrator
  • My Views
    • Only available to you and those you can shared the View with. *Unless you give someone else sharing rights and they also what the View with others
    • Editable within Advanced Find

6) How do I sum numbers in a Dashboard?

Create a Chart that uses the same View as the Chart you want a sum of, make this Chart the same way as the other Chart except graph the summed value, add this to the Dashboard.

7) How do I make a bar graph include a bar totaling the other bars?

  • Create a Chart that shows the total amount
  • You will be able to drill down to show the breakdown of the total amount.

8) What’s new in Microsoft Dynamics 2016?

  • Service Enhancements
    • Knowledge Management
      • Can put Diagrams and Pictures in Articles
      • Can email Knowledge Articles
    • Case Enhancements
      • Process Flow
      • Search Knowledge Articles
      • Streamlined Routing
    • Interactive Service Hub
      • This will be a separate area in CRM
      • More Dynamic Dashboards
      • Resolve, Cancel a case, etc.
    • Field Service
      • Helps with Dispatching
      • Understand what your Field Service Reps are working on
    • CRM App for Outlook
      • Can be used on:
        • Computer’s utilizing Outlook 2013 or 2016 (Recommend staying with the Outlook Plugin)
        • Outlook Web
        • Windows Phone, iPhone or Android Phone
      • Can pick which entity to track against
      • Will only track emails into CRM, will not track appointments
      • Don’t have to open up CRM to view related Records
    • OneNote and Delve Integration

9) Are there any websites/book recommended for reference?

10) I would like to understand how to use the knowledge base; best practices and processes.

faq-service-1

Choose a Template to start from

faq-service-2

Fill in the Article and Submit for Approval.

faq-service-3

Get the Article approved by someone with the proper Security Roles and the Article will be published.

faq-service-4

  • Best Practices:
    • Create new Article Templates as needed
    • Create new Subjects for Articles as needed
    • Enter in a Keyword for the Article so others can search for the Article
    • Once an Article is submitted it must be approved
    • Determine who should approve the Articles and provide the appropriate security settings
    • Set up a Workflow to notify the individual that approves Knowledge Base Articles of the new Article
    • If you reject an Article, provide a reason
    • Create a Dashboard showing the # of Articles created by week by Rep

 

Not subscribed to our blog yet? Be sure to enter your email on the top right of this blog section to receive notification when new blogs are posted with tips, tricks, thought leadership and CRM topics.

The post 10 FAQ’s from Service Professionals of Dynamics 365/CRM appeared first on Ledgeview Partners.

4 Steps to Properly Score Your Website Leads

$
0
0
Score Your Website Leads

If you’re lucky enough to have so many leads you don’t know where to focus your attention, then lead scoring is for you. In a nutshell, lead scoring allows you to assign points to leads based on certain criteria, allowing you to focus your efforts on leads that have higher scores.

So how do you come up with a system for scoring leads? First let’s brush up on our sales funnel basics, then we’ll dig in.

If you visualize the sales funnel, it basically represents a state of sales-readiness for all your leads. At the top of the funnel, you’ll tend to have a big pool of “cool” leads that have done something to indicate their interest in your product/service, but are not really close to buying. Towards the middle of the funnel are “warm” leads that have shown an ongoing interest in your product/service, but still aren’t quite there. And at the bottom of the funnel, you’ve got leads that are “marketing qualified leads”—aka “sales-ready”—aka hot, hot, hot and ripe for the taking!

Score Your Website Leads

Your goal is to focus your time and energy on those hot, marketing-qualified leads, and not waste your time on the leads at the top of the funnel. That’s where lead scoring comes in!

Many customer relationship management (CRM) systems have lead scoring capabilities or add-ins. For instance, PowerObjects uses the PowerPack add-on PowerScore to automatically dole out points to leads based on a wide range of criteria. You may have a different system. No matter what technology you are working with, the basic steps you take to determine how to score your leads should be pretty standard.

Step 1: Figure out what your goal is.

For most sales-type organizations/departments, the goals tend to be straight forward. Your main goal could be to identify which leads are “hot” by analyzing their behavior and/or characteristics to determine which are most likely to buy within a certain timeframe. For some organizations, the goal may be to sort out the leads who are most likely to be open to a phone discussion with a sales rep. For others, it may be just filling out a form on a website. The goal will be unique to every organization.

Step 2: Designate a score you want your leads to get to.

Score Your Website Leads

Step 3: Determine your scoring criteria based on lead behavior.

Step 3. Determine your scoring criteria based on lead behavior.

Scoring can be based on set characteristics of a leads, such as how big the lead’s organization is, whether they are in a target demographic, if they fit a certain geographic region, or have a history with your business.

Scoring can also be based on the leads behavior, so think about the types behavior that indicate positive action in your leads. These are some things you can use to give leads scores through the PowerScore add-on:

  • Opening a page on your website
  • Opening an email you sent
  • Clicking on a link in an email you sent
  • Filling out a web form
  • Filling out a survey
  • Lowering lead score through activity or inactivity

Step 4: Profit!

Kidding (sort of). But really, once you’ve put in place the scoring rules, these “hot” leads that have made it to your goal score should, in theory, be the most valuable, and reward you with a higher close rate and/or a faster time to close.

Further Reading: Using Nurture Campaigns to Coax Your Leads Down the Funnel

Okay, so you know the goal—getting those leads to “sales-ready”—and you know what behaviors you want to score your leads on. Next you’ll want to think about ways to help your leads down the funnel. That’s where nurture campaigns come in! Check out our blog on how to develop compelling content that nurtures your leads and gets them to the bottom of the funnel!

Happy CRM’ing!

Understanding Dynamics 365 Solutions

$
0
0
Microsoft Dynamics 365 allows a developer to package a number of customizations as a solution so they may be installed and managed as a unit rather than individually. By customizations, we mean new entities...(read more)

Make it Your New Year's Resolution to Become a CRM Expert | Attend CRMUG Focus

$
0
0

CRMUG Focus Offers Deep-Dive Training for your Role

x

"New year, new me!" We've all heard that mantra before around this time of year. Instead of committing to daily gym visits or giving up chocolate (seriously, why do that to yourself?), we have the perfect New Year's resolution in mind for you: Register to attend CRMUG Focus, held May 8-9 in St. Louis, MO.

CRMUG Focus is the perfect conference to launch your use of Dynamics CRM/365 to the next level. While CRMUG Summit provides varying levels of education, regarding many different topics that are relevant to a larger audience, CRMUG Focus concentrates on three very specific learning tracks - Sales, Service, Citizen Developer - and offers all sessions in a deep-dive, 90-minute format.

Toss aside your squeaky clean, never-been-used gym shoes, grab your scuba gear, and dive in deep at CRMUG Focus! If you are interested in Power BI, you can also register for PBIUG Focus, held at the same location May 10-11.

Register now to save with Early Bird pricing until March 22.

x

Want to save even more? Become a member of the Dynamics CRM User Group (CRMUG), the supporting organization behind CRMUG Focus.
x

REMINDER: CRMUG FOCUS Call for Proposals are currently being accepted!
 

Click here to submit a proposal for Dynamics CRM/365 sessions. Deadline is January 13.

Also knowledgeable about Power BI? Click here to submit session ideas for PBIUG Focus.

x

Originally posted on crmug.com

 

EMEA Summit – April

$
0
0
I am currently busy planning a Unified Service Desk presentation for the EMEA Summit in April. If you are thinking of attending, you can access the summits website here . There is still plenty of time...(read more)

Solution with ID doesn’t not exist error while using “Applying Solution Upgrade” in Dynamics 365 (CRM 2016 Update 1)

$
0
0
We had a requirement to delete few of the components from the solution and we followed the new feature that is now available for this in product, starting from CRM 2016 Update 1. https://nishantrana.me/2016/10/16/how-to-delete-components-from-managed...(read more)

Hosk’s Top Dynamics 365 Articles of the week – 13th January

$
0
0

Quotes

Positive thinking will let you use the ability which you have, and that is awesome. Zig Ziglar

#HoskWisdom Favoutes this week

  • If recruiters want to be treated with respect, they need to treat people with respect #HoskWisdom

Want more #HoskWisdom then follow #HoskWisdom or follow @BenHosk

Articles of the week

awesome-1

CRM Development hacks

great article with some great link to show all fields, enable all fields, get record guid and links to other pages such as advanced find/solutions.

Azure functions are a useful tool to learn about, to help move long running processes out from Dynamics 365

Best of the week

CRM for Dynamics 365 Top 10 New Features

Dynamics 365 – What does Include entity metadata do

Top 10 Microsoft Dynamics CRM/365 Tips from 2016

Dynamics 365 – Editable Grids

Dynamics 365 – Editable Grids JavaScript Example

How to show signature accepted using Pen Control in Reports & HTML web resources – Dynamics CRM/365

Learning Path authoring now available in Dynamics 365 (online)!

Business Rules – Dynamics 365

Will Dynamics 365 redesign Microsoft Dynamics CRM Online? 

XrmToolBox : Marketing List Manager Plugin

worth a read to refresh me about outer join functionality added to CRM

Replicate Microsoft Dynamics 365 (online) data to Microsoft Azure SQL Database

What’s new for developers: Microsoft Dynamics 365

Microsoft Dynamics 365 App for Field Service – A Walkthrough Tour

 Email Engagement in Dynamics 365 (CRM)

Dynamics 365 – You can’t add new forms to the appointment entity

Executing Dynamics 365 workflows from Microsoft Flow

CRM 2016 – ActivityParty and ActivityParty Lists

WHAT’S NEW IN THE DYNAMICS 365 DEVELOPER TOOLKIT

CRM 2016 – Tips on passing the MB2-712 customization and config exam

Programming

Write a Live Code Analyzer for Your API

Why “Agile” and especially Scrum are terrible

3 Strengths That Make Microsoft Corporation (MSFT) Stock A Buy Now

What are story points

too cool for school – lego kanban board

Other

 The Outrageous Cost of Skipping TDD & Code Reviews

 10 ways to better lead your agile team

Former Navy SEAL commanders explain why they still wake up at 4:30 a.m. — and why you should, too

Managing Your Boss

32 Little Rules I Follow To Live A Life That Feels Good Every Day

4 WAYS TO PUSH THROUGH ADVERSITY AND FAILURE WITHOUT EGO

The Hosk currently reading

The Hosk – just finished reading

Hosk’s CRM Developer Articles

A collection of my favourite CRM Developer articles I have written

CRM 2016 – Tips on passing the MB2-712 customization and config exam

All the CRM 2013 content to help you pass the exam

picture from here


Filed under: CRM 2016, Dynamics 365, Hosk’s Top CRM articles of the week

Linkliste Dynamics 365

Viewing all 28716 articles
Browse latest View live


Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>