0

SQL Server 2005 からレコードを読み取り、返されたレコードセットを次のコードで SQLite に書き込みます。

私のコンパイラはLazarus 1.0.12で、qt1は「sqlquery」で、「qrystkmas」はZeos dboのZtableです...

しかし、動作はかなり遅いです。テスト時間は

開始時刻: 15:47:11 終了時刻: 16:19:04 レコード数: 19500

したがって、SQL Server と SQL Server CE のペアでは、Delphi プロジェクトで 2 ~ 3 分未満です。

このプロセスをスピードアップするにはどうすればよいですか?

コード:

  Label2.Caption:=TimeToStr(Time);
  if Dm.Qt1.Active then Dm.Qt1.Close;
    Dm.Qt1.SQL.Clear;
    Dm.Qt1.SQL.Add('  select ');
    Dm.Qt1.SQL.Add('   st.sto_kod, st.sto_isim,st.sto_birim1_ad,  ');
    Dm.Qt1.SQL.Add('   st.sto_toptan_vergi,st.sto_perakende_vergi,');
    Dm.Qt1.SQL.Add('   st.sto_max_stok,st.sto_min_stok, ');
    Dm.Qt1.SQL.Add('   sba.bar_kodu,   ');
    Dm.Qt1.SQL.Add('   stf.sfiyat_fiyati  ');
    Dm.Qt1.SQL.Add('  from MikroDB_V14_DEKOR2011.dbo.STOKLAR st ');
    Dm.Qt1.SQL.Add('  left JOIN MikroDB_V14_DEKOR2011.dbo.BARKOD_TANIMLARI sba on sba.bar_stokkodu=st.sto_kod ');
    Dm.Qt1.SQL.Add('  left JOIN MikroDB_V14_DEKOR2011.dbo.STOK_SATIS_FIYAT_LISTELERI stf on stf.sfiyat_stokkod=st.sto_kod  ');
    Dm.Qt1.SQL.Add('  where LEFT(st.sto_kod,1)=''5'' --and stf.sfiyat_listesirano=1 ');
    Dm.Qt1.Open;
    Dm.qryStkMas.Open;
    Dm.qrystkmas.First;

    While not Dm.Qt1.EOF do
    begin
      Dm.qryStkMas.Append;
      Dm.qryStkMas.FieldByName('StkKod').AsString :=Dm.Qt1.FieldByName('sto_kod').AsString;
      Dm.qryStkMas.FieldByName('StkAd').AsString  :=Dm.Qt1.FieldByName('sto_isim').AsString;
      Dm.qryStkMas.FieldByName('StkBrm').AsString :=Dm.Qt1.FieldByName('sto_birim1_ad').AsString;
      Dm.qryStkMas.FieldByName('StkBar').AsString :=Dm.Qt1.FieldByName('bar_kodu').AsString;
      Dm.qryStkMas.FieldByName('StkKdv1').AsFloat :=Dm.Qt1.FieldByName('sto_toptan_vergi').AsFloat;
      Dm.qryStkMas.FieldByName('StkKdv2').AsFloat :=Dm.Qt1.FieldByName('sto_perakende_vergi').AsFloat;
      Dm.qryStkMas.FieldByName('StkGir').AsFloat  :=0;
      Dm.qryStkMas.FieldByName('StkCik').AsFloat  :=0;
      Dm.qryStkMas.FieldByName('YeniStk').AsBoolean :=False;
      Dm.qryStkMas.FieldByName('MinStk').AsFloat  :=Dm.Qt1.FieldByName('sto_min_stok').AsFloat;
      Dm.qryStkMas.FieldByName('MaxStk').AsFloat  :=Dm.Qt1.FieldByName('sto_max_stok').AsFloat;
      Dm.qryStkMas.FieldByName('StkGrp1').AsString:='';
      Dm.qryStkMas.FieldByName('StkGrp2').AsString:='';
      Dm.qryStkMas.FieldByName('StkGrp3').AsString:='';
      Dm.qryStkMas.FieldByName('StkGrp4').AsString:='';
      Dm.qryStkMas.FieldByName('StkFytno').AsInteger:=1;
      Label1.Caption:=Dm.Qt1.FieldByName('sto_isim').AsString;
      Dm.qryStkMas.Post;
      Dm.Qt1.Next;
    end;
    Dm.qryStkMas.Close;
   label3.Caption:=timetostr(time);
4

2 に答える 2

4

物事をスピードアップするための最初のステップは診断です。

測定
選択と挿入を分割することで測定できますが、SQL 自体からいくつかの診断を取得することもできます。

SQLite でクエリの前にキーワードを付けると、EXPLAIN使用されているインデックスとステートメントが内部でどのように処理されているかがわかります。こちらを参照してください: http://www.sqlite.org/eqp.html
これは最適化のための非常に貴重な情報です。
MS SQL Server では、GUI に移動し、クエリを入力して、推定クエリ プラン ボタンをクリックします。次を参照してください。.

一番時間がかかるのは?select遅いですか、またはですinsert

SELECT
選択は通常、評価されるフィールドにインデックスを配置することで高速化されます。
あなたの場合、結合基準に含まれるフィールド。
where 句のフィールドは関数を使用しており、MSSQL の関数にインデックスを配置することはできません (PostgreSQL と Oracle では可能です)。

INSERTインデックスを無効
にすること で挿入が高速化されます。 一般的なトリックの 1 つは、挿入バッチの前にすべてのインデックス作成を無効にし、挿入バッチの完了後に再度有効にすることです。 これは通常、(項目ごとに) 全体を一度にソートする方が高速であり、個々の挿入後に再利用し続けるため、より効率的です。

トランザクション保護を無効にすることもできます。これにより、電源/ディスクなどの障害が発生した場合にデータが破損する可能性があるため、警告
を考慮してください。こちらを参照してください:

コードに関するコメント
SQL 選択ステートメントを使用してデータを選択しますが、データセットappendfieldbyname()メソッドを使用して挿入します。FieldByName は、名前のルックアップを毎回行うため、非常に遅いことで有名です。
FieldByName はループ内で使用しないでください
。代わり にinsertSQL ステートメントを作成します。
パラメータを使用することも、そこに値をハードペーストすることもできることに注意してください。
実験を行って、どちらが速いかを確認してください。

About.comには、排除することでデータベースアクセスを高速化する方法に関する素晴らしい記事がありますFieldByName: http://delphi.about.com/od/database/ss/faster-fieldbyname-delphi-database.htm

于 2013-10-11T14:24:32.427 に答える
3

トランザクションで挿入をラップしようとしましたか? While... の前にトランザクションを BEGIN し、...End の後に COMMIT する必要があります。試してみてください、役立つかもしれません。

編集: 改善が得られた場合、それは SQLite へのデータベース接続が「自動コミット」モードで設定されているためです。このモードでは、すべての操作 (.Append など) が他のすべての操作とは独立して行われ、SQLite は十分にスマートです。データベースの ACID プロパティを確認します。これは、書き込み操作ごとに、データベースがハード ドライブに 1 回以上の書き込みを行うことを意味しますが、これは低速です。明示的にトランザクションを作成することにより (自動コミットをオフにします...)、トランザクション内の書き込み操作をグループ化し、トランザクションを明示的にコミットするときにデータベースがハード ドライブに発行する書き込みの数を大幅に減らすことができます。

于 2013-10-11T14:16:52.477 に答える