EntityFramework6 / Npgsql:如何将 orderBy nulls 最后转换为 SQL 查询

问题描述 投票:0回答:2

我正在使用 EntityFramework6.Npgsql 并正在处理具有数百万条记录的表。某些实体具有

timestamp
/
DateTime
列,允许
null
值。用户经常需要对此列进行排序,并希望在
null
asc
排序中最后显示
desc
值。该列有两个用于两种排序类型的索引,它们都设置为
nulls last

我知道在 SQL 中我可以添加

order by "DateColumn" desc nulls last
并且 postgres 使用适当的索引并且查询返回(分页,例如 25 条记录)会在几毫秒内产生结果。

但是,使用 EntityFramework,为了最后对空值进行降序排序,我必须添加如下内容:

entities.MyEntity
    .OrderByDescending(e => e.DateColumn.HasValue)
    .ThenByDescending(e => e.DateColumn)

然而,这会转换为包含类似排序内容的查询:

SELECT 
    CASE
        WHEN ("Extent1"."DateColumn" IS NOT NULL) THEN (TRUE)
        ELSE (FALSE)
    END AS "C1"

...

ORDER BY "C1", "DateColumn" DESC

这按预期工作,但查询需要几秒钟(而不是几毫秒)才能执行,因为它无法使用索引。

我尝试使用相同的表达式向列添加索引,但 postgres 在执行查询时似乎没有使用索引。

我必须使用哪些选项才能在 EntityFramework / Npgsql 中编写可以转换为所需 SQL 的查询 (

order by "DateColumn" desc nulls last
)?有没有办法拦截/覆盖 Linq 查询如何转换为 SQL?

c# postgresql entity-framework-6 npgsql
2个回答
0
投票

回答我自己的问题...

虽然仍然无法让 Linq 生成使用

nulls last
排序的 SQL 查询,但我能够为 null 检查和日期列本身创建一个组合索引,该索引正在由 postgres 使用:

CREATE INDEX "MyTable_IX_DateCombined"
  ON "MyTable"
  USING btree
  ((
  CASE
    WHEN "DateColumn" IS NOT NULL THEN true
    ELSE false
  END) DESC, "DateColumn" DESC);

由于在任何一种情况下我都必须创建一个额外的索引,所以我认为这个解决方案目前已经足够好了。


0
投票

谢谢!我们有相同但更简单的索引

CREATE INDEX "MyTable_IX_DateCombined"
 ON "MyTable"
 USING btree
 (("DateColumn" IS NOT NULL ) DESC, "DateColumn" DESC);

因为我们的 ef core 6 版本会翻译查询所以

ORDER BY ("DateColumn" IS NOT NULL ) DESC, "DateColumn" DESC
© www.soinside.com 2019 - 2024. All rights reserved.