Reputation: 708
This seems to be a very common question but did not get the solution for all the cases.
I have searched lots of articles to optimize the pagination query in MYSQL, I found the Seek Method as the best solution.
But in every example of seek method, I found that order by clause on either number or date type fields, What if we are ordering by a varchar type column(eg: first_name) which may contain blank and null values too, I tried (first_name, id) < (null, 15) AND (first_name, id) < ('', 15) which show uncertain result.
Please suggest how can we handle these cases too in seek method.
Upvotes: 2
Views: 4550
Reputation: 4462
Along with the usage of NULL there is another issue that is not yet pointed out by any answer.
You can't use that syntax with MySQL. Example: (first_name, id) < ('Alex', 15)
This is called “row values” syntax. Even if you don't use NULL and give a proper value, MySQL understands it but isn't able to use index in a proper way to produce the desired sort order and hence you aren't seeing results you expect.
Even though the row values syntax is part of the SQL standard, only a few databases support it. SQL Server 2017 does not support row values at all. The Oracle database supports row values in principle, but cannot apply range operators on them (ORA-01796). MySQL evaluates row value expressions correctly but cannot use them as access predicate during an index access. DB2 (only LUW, since 10.1) and PostgreSQL (since 8.4), however, have a proper support of row value predicates and uses them to access the index if there is a corresponding index available.
Good resource on this topic: https://use-the-index-luke.com/sql/partial-results/fetch-next-page
Upvotes: 0
Reputation: 142453
WHERE (first_name, id) < ('', 15)
Is nifty syntax but performance sucks! The optimizer does not know how to use any index to help with such. You must turn it into a complex AND
and OR
expression. And you must have INDEX(first_name, id)
in that order.
As for the expression, etc, the details are spelled out here.
PS, don't use first_name < NULL
; NULL
compared to anything is always FALSE
. For example:
mysql> SELECT 'Rick' < NULL, 'Rick' > NULL, 'Rick' = NULL, 'Rick' != NULL;
+---------------+---------------+---------------+----------------+
| 'Rick' < NULL | 'Rick' > NULL | 'Rick' = NULL | 'Rick' != NULL |
+---------------+---------------+---------------+----------------+
| NULL | NULL | NULL | NULL |
+---------------+---------------+---------------+----------------+
(And NULL
works like FALSE
when tested in a WHERE
.)
Upvotes: 1
Reputation: 48850
It doesn't matter which types of columns you use to order the rows, as long as they are "sortable" by the database. This includes pretty much all numbers, varchars, dates/times, etc.
The common exception are heavy data fields such as BLOB
, CLOB
, BINARY
, etc. This list is very database-specific, so check which data types can participate in an ORDER BY
in your database.
Also, please note that to use the Seek Method correctly the list of columns you use to order must produce a unique key. Otherwise, the pagination may work "funny".
Upvotes: 2