使用Seek方法优化分页查询

时间:2018-07-03 14:08:01

标签: mysql sql pagination query-optimization

这似乎是一个非常普遍的问题,但并未解决所有情况。

我搜索了很多文章以优化MYSQL中的分页查询,我发现Seek Method是最佳解决方案。

但是在seek方法的每个示例中,我发现在number或date类型字段上的order by子句,如果我们通过也可能包含空值和null值的varchar类型列(例如first_name)排序,该怎么办?尝试(first_name,id)<(null,15)AND(first_name,id)<('',15)显示不确定的结果。

请提出在搜索方法中我们也应如何处理这些情况。

3 个答案:

答案 0 :(得分:1)

    WHERE (first_name, id) < ('', 15)

是漂亮的语法但是性能糟透了!优化器不知道如何使用任何索引来提供帮助。您必须将其转换为复杂的ANDOR表达式。 并且您必须按 顺序使用INDEX(first_name, id)

关于表达式等,详细信息将详细说明here

PS,请勿使用first_name < NULL;与任何事物相比,NULL始终是FALSE。例如:

mysql> SELECT 'Rick' < NULL, 'Rick' > NULL, 'Rick' = NULL, 'Rick' != NULL;
+---------------+---------------+---------------+----------------+
| 'Rick' < NULL | 'Rick' > NULL | 'Rick' = NULL | 'Rick' != NULL |
+---------------+---------------+---------------+----------------+
|          NULL |          NULL |          NULL |           NULL |
+---------------+---------------+---------------+----------------+

(在NULL中进行测试时,FALSE的作用类似于WHERE。)

答案 1 :(得分:0)

用于排序行的列的类型无关紧要,只要它们可以被数据库“排序”即可。这几乎包括所有数字,varchar,日期/时间等。

常见的例外是繁重的数据字段,例如BLOBCLOBBINARY等。此列表是特定于数据库的,因此请检查哪些数据类型可以参与{ {1}}在您的数据库中。

另外,请注意,要正确使用“查找方法”,您要订购的列列表必须产生一个唯一键。否则,分页可能会“有趣”。

答案 2 :(得分:0)

除了使用NULL外,还没有任何答案指出另一个问题。

您不能在MySQL中使用该语法。 例如:(first_name,id)<('Alex',15)

这称为“行值”语法。即使您不使用NULL并提供适当的值,MySQL也会理解它,但无法以正确的方式使用索引来产生所需的排序顺序,因此您看不到预期的结果。

尽管行值语法是SQL标准的一部分,但只有少数数据库支持它。 SQL Server 2017根本不支持行值。 Oracle数据库原则上支持行值,但是不能在它们上应用范围运算符(ORA-01796)。 MySQL会正确评估行值表达式,但不能在索引访问期间将它们用作访问谓词。但是,DB2(从10.1开始只有LUW)和PostgreSQL(从8.4开始)都对行值谓词提供了适当的支持,并在有相应索引可用时使用它们来访问索引。

有关此主题的好资源:https://use-the-index-luke.com/sql/partial-results/fetch-next-page