Best Practices - Avoid Unnecessary "Order By"
The purpose of this document is to provide best practices to access databases with large datasets when developing in X3 syntax.
When using a For [ABV]
loop on a table, the X3 engine sends a Select ...
statement to the database, with an Order By
clause by default. In most cases, this clause is critical to ensure the consistency of the expected results. Below are examples of situations where the Order By
clause is useful:
However, the Order By
clause can cause serious performance issues if a Select ...
statement is performed on a large dataset (in the case it is not useful).
By default, the X3 engine always sends an Order By
clause. It generates the SQL sentences based on the various X3 instructions.
Example:For [table]
does the following:
For[table]KEYNAME
, the Order By
clause defined by the key is sent to the database.For [table]
(without key name), an Order By
clause is sent based on default rules:File
declaration has been written with an Order By Key
clause or an Order With
clause, this clause will be used.[G:table]currind
variable has been assigned).Order By
clause, use the following syntax:>>For [table]reckey
>> Local File MYTABLE [XXX] Where ...>> If rowcount([XXX])<>0 : # records have been foundThis performs a
count(*)
type of SQL query.>> Local File MYTABLE [XXX] Where ...>> Look [XXX]reckey First>> If fstat=0 : # There is a recordThis performs a query without order and with hints, which tells the system to use a "first row" type of implementation.
As a test, a search based on a post code value that matches approximately 40 lines was performed on POSCOD table (1,200,00 records). The script always starts with:
>> Local File POSCOD [POS]>> Filter [POS] Where POSCOD="..."
The following lines depend on the results expected:
Syntax | Script written to get the result | Relative time | Relative time if an index exists |
---|---|---|---|
1 | For [POS] | 900 (930 if no break is done) | 15 (no break done) |
2 | For [POS]reckey | 15 (900 if no break is done) | 15 (no break done) |
3 | FOUND=nbrecord([POS]) | 500 | 3 |
4 | Look [POS]reckey First | 5 | 3 |
5 | Read [POS]reckey First | 5 | 3 |
order by
clause still saves time. For only one fetch operation (syntax 4 vs syntax 5), there is no significant difference.If this script is frequently used and no standard index exists, consider creating an additional index, or at least an optimization index for the customers that are frequently in this situation.
For, Reckey, Order By, Filter.