|
| 1 | +--- |
| 2 | +title: "Paging behaviors and ordering (Common Data Service) | Microsoft Docs" # Intent and product brand in a unique string of 43-59 chars including spaces |
| 3 | +description: "Learn about the different paging behaviors for FetchXML queries and how you can write queries to get the desired paging results." # 115-145 characters including spaces. This abstract displays in the search result. |
| 4 | +ms.custom: "" |
| 5 | +ms.date: 7/20/2020 |
| 6 | +ms.reviewer: "pehecke" |
| 7 | +ms.service: powerapps |
| 8 | +ms.topic: "article" |
| 9 | +author: "NHelgren" # GitHub ID |
| 10 | +ms.author: "nhelgren" # MSFT alias of Microsoft employees only |
| 11 | +manager: "mayadu" # MSFT alias of manager or PM counterpart |
| 12 | +search.audienceType: |
| 13 | + - developer |
| 14 | +search.app: |
| 15 | + - PowerApps |
| 16 | + - D365CE |
| 17 | +--- |
| 18 | + |
| 19 | +# Paging behaviors and ordering |
| 20 | + |
| 21 | +When querying data using FetchXML, paging query results can make viewing large |
| 22 | +volumes of information easier. It is important when using paging to include |
| 23 | +ordering parameters as well. Without proper ordering, paging requests for the |
| 24 | +“next 50” records can result in retrieving the same records across multiple |
| 25 | +pages making reviews and edits much more difficult. Proper page ordering |
| 26 | +requires including unique values to help identify which records are included in |
| 27 | +a page. |
| 28 | + |
| 29 | +## Legacy paging |
| 30 | + |
| 31 | +Legacy paging within the Common Data Service loads all the results of the query |
| 32 | +up to the current page into memory on the server, selects the number of records |
| 33 | +that are needed for the page, and then ignores the rest. This has benefits such |
| 34 | +as quick back/forward paging through the data or skipping to a specific page, |
| 35 | +but it also has restrictions such as a 50K row limit, performance issues with |
| 36 | +large complex queries, and arbitrarily sorted distinct query results. |
| 37 | + |
| 38 | +## Ordering with a paging cookie |
| 39 | + |
| 40 | +When paging with ordering, a cache of the previous page’s results is stored in a |
| 41 | +paging cookie. This is used to calculate what the next page of data should |
| 42 | +display. |
| 43 | + |
| 44 | +If a user does not specify any “order by” parameters, the system will |
| 45 | +automatically insert “order by "\<\<entity name\>\>".\<\<entityId\>\> asc” to |
| 46 | +provide some basic ordering. Depending on the data that is being queried, this |
| 47 | +may result in inadequate and unexpected results as a single system user can be |
| 48 | +associated with multiple records within any query. |
| 49 | + |
| 50 | +If distinct FetchXML queries are being used, the system will not add any |
| 51 | +additional ordering due to potential impacts to the data returned. In these |
| 52 | +cases, users will have to add at least a single ordering value for a more |
| 53 | +consistent paging experience. |
| 54 | + |
| 55 | +> [!NOTE] |
| 56 | +> Paging using FetchXML for Common Data Service is dynamic. The page a |
| 57 | +> record appears on is determined at the time that each page is rendered. If 1000 |
| 58 | +> records are being displayed 50 to a page, the first 50 records are displayed as |
| 59 | +> page one. When page two is requested, the system determines what the next 50 |
| 60 | +> records should be at the time of request. Because of this, it would not be |
| 61 | +> possible to use the new paging functionality for back paging. Legacy behavior is |
| 62 | +> used for back paging which will have reduced performance and any returns after |
| 63 | +> page 500 cannot be “paged back” due to legacy limitations.  |
| 64 | +
|
| 65 | +### Why ordering is important |
| 66 | + |
| 67 | +If a query is run to retrieve all records with a state of “Open” this could |
| 68 | +result in 1000 returns. When paging from page one to page two, there is no way |
| 69 | +for the system to know which orders to display on page two because all of the |
| 70 | +records have the same state. The paging of these records will not be efficient |
| 71 | +or consistent. |
| 72 | + |
| 73 | +Providing an “order by” value gives the paging cookie the ability to order the |
| 74 | +data by an additional value and recognize the last record in a page based on the |
| 75 | +values provided. |
| 76 | + |
| 77 | +#### Example 1 |
| 78 | + |
| 79 | +A query is created to get all records with a state of ‘Open’, include the status |
| 80 | +for every record, and show three records per page. The query is then ordered by |
| 81 | +status. The query result would page as shown in the following table: |
| 82 | + |
| 83 | +| State | Status | Page | |
| 84 | +|-----------|------------|---------------| |
| 85 | +| Open | Active | 1 | |
| 86 | +| Open | Active | 1 | |
| 87 | +| Open | Active | End of page 1 | |
| 88 | +| Open | Active | | |
| 89 | +| Open | Active | | |
| 90 | +| Open | Inactive | | |
| 91 | +| Open | Inactive | | |
| 92 | + |
| 93 | +The paging cookie will save information about the last record on the page, but |
| 94 | +when it’s time to get page two in this example, there is no unique identifier to |
| 95 | +ensure that the next page populated uses the unviewed records or include the |
| 96 | +first two records that were on page one. |
| 97 | + |
| 98 | +To solve this problem, queries should include “order by” columns that have |
| 99 | +unique values. It is possible to use multiple “order by” values. Below is a |
| 100 | +better way to order data for this query: |
| 101 | + |
| 102 | +#### Example 2 |
| 103 | + |
| 104 | +A query is created to get all records of a state of ‘Open’, any status, include |
| 105 | +the Case IDs, and show three records per page. It orders by status and by Case |
| 106 | +ID (a unique identifier) which will order in ascending order. The query result |
| 107 | +would page the results as shown below: |
| 108 | + |
| 109 | +| State | Status | Case ID | Page | |
| 110 | +|-----------|------------|-------------|---------------| |
| 111 | +| Open | Active | Case-0010 | 1 | |
| 112 | +| Open | Active | Case-0021 | 1 | |
| 113 | +| Open | Active | Case-0032 | End of Page 1 | |
| 114 | +| Open | Active | Case-0034 | | |
| 115 | +| Open | Active | Case-0070 | | |
| 116 | +| Open | Inactive | Case-0015 | | |
| 117 | +| Open | Inactive | Case-0047 | | |
| 118 | + |
| 119 | +The query results are first ordered by the Status, and then ordered by the Case |
| 120 | +ID in ascending order. When page two is generated, the result would be as shown |
| 121 | +below: |
| 122 | + |
| 123 | +| State | Status | Case ID | Page | |
| 124 | +|-----------|------------|-------------|---------------| |
| 125 | +| Open | Active | Case-0010 | | |
| 126 | +| Open | Active | Case-0021 | | |
| 127 | +| Open | Active | Case-0032 | End of Page 1 | |
| 128 | +| Open | Active | Case-0034 | 2 | |
| 129 | +| Open | Active | Case-0070 | 2 | |
| 130 | +| Open | Inactive | Case-0015 | | |
| 131 | +| Open | Inactive | Case-0047 | | |
| 132 | + |
| 133 | +When generating page two of this query set, the cookie will have Case-0032 |
| 134 | +stored as the last record in the first page, so page two will pick up at the |
| 135 | +next record in the set after that record. This will allow for more consistent |
| 136 | +results. |
| 137 | + |
| 138 | +### Ordering suggestions |
| 139 | + |
| 140 | +Listed below are some suggestions for improving ordering of paging results, along with some areas to avoid. |
| 141 | + |
| 142 | +#### Best ordering |
| 143 | + |
| 144 | +- Always include a column that has a unique identifier (i.e., entity ID |
| 145 | + columns, auto-number columns, user/contact IDs) |
| 146 | + |
| 147 | +#### Good ordering |
| 148 | + |
| 149 | +- Include multiple fields that will most likely result in unique combinations: |
| 150 | + - First name + last name + email address |
| 151 | + - Full name + email address |
| 152 | + - Email address + company name |
| 153 | + |
| 154 | +#### Poor ordering |
| 155 | + |
| 156 | +- Orders that do not include unique identifiers |
| 157 | + |
| 158 | +- Orders that have single or multiple fields that are not likely to provide |
| 159 | + uniqueness such as: |
| 160 | + - Status and state |
| 161 | + - Option sets or booleans |
| 162 | + - Name values by themselves (i.e., last only, first only, company name |
| 163 | + only) |
| 164 | + - Text fields like titles, descriptions, multi-line text |
| 165 | + - Non unique number fields |
| 166 | + |
| 167 | +### Ordering and multiple entity queries |
| 168 | + |
| 169 | +Sometimes data is needed that spans multiple entities and must be queried with a |
| 170 | +table JOIN. In these cases, ordering can be included for both entities in the |
| 171 | +query. Make sure to use at least one column with a unique ID per entity to |
| 172 | +ensure the paging provides the best results. However, the query will be |
| 173 | +downgraded to legacy paging, where no paging cookie will be returned, in these |
| 174 | +cases due to limitations of the N:1 relationship structure that could result in |
| 175 | +missing data. |
| 176 | + |
| 177 | +### See Also |
| 178 | + |
| 179 | +[Page large result sets with FetchXML](page-large-result-sets-with-fetchxml.md) |
0 commit comments