2017-07-12 8 views
3

私は4つのテーブルを持つ単純なDBを持っています。表Resultsには18の列があります。それらのうち3つは外部キーです。それは一つのテーブル内のレコードの数を取得するのに約40秒かかりFSharp.Data.SqlProviderが遅い

#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) 

:私はこのコードですべての結果(約800K)の数を取得しようとしています。

どうして遅いですか?私は間違って何をしていますか?

+0

を使用できることを意味しているのIQueryableを実装 'Seq.length'は、全体の結果シーケンスが評価されます。そのため、行数をカウントするだけでなく、すべてのデータを取得することが必要です。何行ありますか? – TheQuickBrownFox

+0

質問が更新されました - 約800000です。 – Alamakanambra

+2

あなたのコードは 'SELECT COUNT(*)'を実行していません。メモリ内の*すべてのデータをロードし、返されたオブジェクトを数えています。私は40秒で800Kの行を読み込むのが速いと言うでしょう –

答えて

4

タイプを使用すると、クエリ式を書いたりQueryable.Count

open System.Linq 

dbm.Dbo.Results |> Queryable.Count 

または

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

ですから、この 'query {..}'を使ってデータベースからデータを取得する必要があります。しかし、この 'query {..}を避ける方法はありますか?} '構文?私は 'pipe |>'と 'Seq.someFunction'を使ってデータを処理することは本当にいい方法ですか? – Alamakanambra

+1

LINQ演算子の使用方法は既に掲載しています。 'bm.Dbo.Results |> Queryable.Count'です。 'dbm.Dbo.Results'はIQueryable です。 Enumerable/Seq関数ではなく、 'Queryable'関数を使うべきです –

3

テーブルで直接クエリを実行し、結果をサーバーに返すようにしてください。たとえば、私は瞬時に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によって返さ

+1

OPは 'SqlDataConvider'を使用していますが、' SqlDataConnection'ではありません。 –

+0

@PanagiotisKanavosああ、はい、私は、古いSQL Serverデータベースが元のSQLDataProviderに接続されているのを忘れていました。私はクエリのバージョンが動作するはずだと思う。また、System.Linq名前空間を開くと、Countのようなlinq拡張メソッドもうまくいくはずです。あなたがコメントしたところでは、クライアントではなくサーバー上でクエリを実行し、結果を取得するだけです。 – s952163