F# 查询表达式是不是具有与本机 SQL 相同的性能?
Posted
技术标签:
【中文标题】F# 查询表达式是不是具有与本机 SQL 相同的性能?【英文标题】:Do F# Query Expressions have same performance as Native SQL?F# 查询表达式是否具有与本机 SQL 相同的性能? 【发布时间】:2021-09-25 12:49:00 【问题描述】:我注意到 F# 查询表达式示例看起来好像在进行计算之前获取了表的全部内容。这似乎比原生 SQL 效率低。或者性能应该是一样的。
// A query expression.
let query1 =
query
for customer in db.Customers do
select customer
【问题讨论】:
对应的SQL也会是SELECT * FROM customers
,所以我看不出抓取整张表有什么区别...?
我只是从网上复制并粘贴了一个示例。但是假设我们有一个 1000 万条记录表,并且我们想要获取最近添加的条目。 F# 是否会检索 1000 万的整个列表,然后执行计算以获取最新条目?还是先在数据库中进行计算,然后将1条记录发送到f#
如果您在 F# 查询中仅获取 TOP 1
记录,那么通常应该转换为仅在 SQL 中获取 TOP 1
记录。这里的关键字是一般 - 这是它在大多数情况下应该工作的方式,但在某些情况下它的工作效果可能不如你希望的那样好。我认为在大多数情况下信任系统是合理的,但有一些诊断程序来仔细检查是很有用的。
【参考方案1】:
F# 查询表达式非常聪明。除了他们使用引号(类似于System.Linq.Expressions
)将代码转换为SQL之外,我并不完全了解它们是如何工作的。 ORM 有 measurable overhead,原始查询会更快,但它们能够生成优化查询
鉴于这些模型和 ef-core 上下文
[<CLIMutable>] type Address = Id: int; City: string; Country: string
[<CLIMutable>] type Person = Id: int; Name: string; Age: int; Address: Address
type PeopleContext() =
inherit DbContext()
[<FSharp.Core.DefaultValue>]
val mutable _people : DbSet<Person>
member db.People
with get () = db._people
and set value = db._people <- value
override _.OnConfiguring options =
options.UseSqlite("Data source=db.db3") |> ignore
我已经创建了这个查询
query
for person in ctx.People do
where (person.Age > 21)
select person.Address.City
take 1
|> Seq.toArray |> printfn "%A"
翻译成这个sql
SELECT "a"."City"
FROM (
SELECT "p"."AddressId"
FROM "People" AS "p"
WHERE "p"."Age" > 21
LIMIT @__p_0
) AS "t"
【讨论】:
以上是关于F# 查询表达式是不是具有与本机 SQL 相同的性能?的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate + Java 性能较慢,但当我将 TOAD 与相同的本机 Oracle 查询一起使用时性能较快
如何通过 Spring Boot JPA 执行具有 INTERVAL 子句的本机 SQL 查询?
如何在 Spring Data JPA 中使用 CTE 表达式 WITH 子句