FSharp.Data.SqlProvider 很慢

FSharp.Data.SqlProvider is slow

我有一个简单的数据库,有 4 个 tables。 Table Results 有 18 列。其中 3 个是外键。我正在尝试使用此代码获取所有结果的数量(大约 800k):

#I @"..\packages\SQLProvider.1.1.3\lib"
#r "FSharp.Data.SqlProvider.dll" 
open FSharp.Data.Sql


let [<Literal>] ConnectionStringmdf = @"Data Source=(localdb)\MSSQLLocalDB;AttachDbFilename=C:\Users\Me\Desktop\myDb.mdf;Integrated Security=True;Connect Timeout=10"    

type Sqlmdf = SqlDataProvider< 
              ConnectionString =   ConnectionStringmdf,
              DatabaseVendor = Common.DatabaseProviderTypes.MSSQLSERVER,
              IndividualsAmount = 1000,
              UseOptionTypes = true, 
              CaseSensitivityChange = Common.CaseSensitivityChange.ORIGINAL
              >
let dbm = Sqlmdf.GetDataContext()

printfn "Results count:\t %i" (dbm.Dbo.Results |>  Seq.length ) 

一次table记录的计数需要大约 40 秒。

为什么这么慢?我究竟做错了什么?

您应该直接在 table 上执行查询,然后让服务器 return 将结果发送给您。例如,我立即得到 8M 行数:

type dbSchema = SqlDataConnection<connectionString1>

let dbx = dbSchema.GetDataContext()
dbx.DataContext.ObjectTrackingEnabled <- false
dbx.DataContext.CommandTimeout <- 60
let table1 = dbx.MyTable

table1.Count()
//val it : int = 7189765

您也可以将其包装到查询中。

这是一个查询版本,(除非 sqlprovider 不计算在内)应该也适用于其他 TP。同样,速度几乎是瞬间的。

query { for row in table1 do 
        select row
        count
        } 

我用 SqlDataProvider 进行了相同的测试,结果相似。如有必要,打开 System.Linq 命名空间以访问 .Count() 扩展功能。

SqlDataProvider 返回的类型实现了 IQueryable,这意味着您可以编写查询表达式或使用 Queryable.Count

open System.Linq

dbm.Dbo.Results |> Queryable.Count 

query { for it in dbm.Dbo.Results do
        count
      }