UniDAC使用教程(八):批處理操做

下載UniDAC最新版本數據庫

Universal Data Access Components (UniDAC)是一款通用數據庫訪問組件,提供了多個數據庫的直接訪問,如針對Windows的Delphi, C++Builder, Lazarus (以及 Free Pascal) , Mac OS X, iOS, Android, Linux和64和32位的FreeBSD等等。咱們將長期的經驗集於這個小組件,提供統一的數據庫鏈接訪問(如oracle、微軟SQL等等)。這意味着您能夠在您的項目之間輕鬆地切換不一樣的數據庫,以及建立跨數據庫應用程序接口。數組

現代數據庫處理的數據量穩步增加。在這方面,存在一個嚴重的問題——數據庫性能。必須儘快執行插入、更新和刪除操做。所以,Devart提供了幾種解決方案來加速處理大量數據。所以,例如,TUniLoader支持向數據庫插入大量數據。不幸的是,TUniLoader只容許插入數據——它不能用於更新和刪除數據。服務器

新版本的Devart Delphi數據訪問組件引入了大數據處理的新機制-批處理操做。關鍵是隻執行一個參數化的修改SQL查詢。多個更改是因爲這樣一個查詢的參數不是單個值,而是一個完整的值數組。這種方法極大地提升了數據操做的速度。此外,與使用TUniLoader相比,批處理操做不只能夠用於插入,還能夠用於修改和刪除。網絡

讓咱們以包含最流行數據類型屬性的BATCH_TEST表爲例,更好地瞭解批處理操做的功能。oracle

Batch_Test表生成腳本

For Oracle:性能

1大數據

2ui

3spa

4code

5

6

7

8

9

CREATE TABLE BATCH_TEST

(

  ID     NUMBER(9,0),

  F_INTEGER  NUMBER(9,0),

  F_FLOAT  NUMBER(12,7),

  F_STRING   VARCHAR2(250),

  F_DATE  DATE,

  CONSTRAINT PK_BATCH_TEST PRIMARY KEY (ID)

)

For MS SQL Server:

1

2

3

4

5

6

7

8

9

CREATE TABLE BATCH_TEST

(

  ID    INT,

  F_INTEGER INT,

  F_FLOAT FLOAT,

  F_STRING  VARCHAR(250),

  F_DATE  DATETIME,

  CONSTRAINT PK_BATCH_TEST PRIMARY KEY (ID)

)

For PostgreSQL:

1

2

3

4

5

6

7

8

9

CREATE TABLE BATCH_TEST

(

  ID    INTEGER,

  F_INTEGER INTEGER,

  F_FLOAT DOUBLE PRECISION,

  F_STRING  VARCHAR(250),

  F_DATE  DATE,

  CONSTRAINT PK_BATCH_TEST PRIMARY KEY (ID)

)

For InterBase:

1

2

3

4

5

6

7

8

CREATE TABLE BATCH_TEST

(

  ID    INTEGER NOT NULL PRIMARY KEY,

  F_INTEGER INTEGER,

  F_FLOAT FLOAT,

  F_STRING  VARCHAR(250),

  F_DATE  DATE

)

For MySQL:

1

2

3

4

5

6

7

8

9

CREATE TABLE BATCH_TEST

(

  ID    INT,

  F_INTEGER INT,

  F_FLOAT FLOAT,

  F_STRING  VARCHAR(250),

  F_DATE  DATETIME,

  CONSTRAINT PK_BATCH_TEST PRIMARY KEY (ID)

)

For SQLite:

1

2

3

4

5

6

7

8

9

CREATE TABLE BATCH_TEST

(

  ID     INTEGER,

  F_INTEGER  INTEGER,

  F_FLOAT  FLOAT,

  F_STRING  VARCHAR(250),

  F_DATE  DATETIME,

  CONSTRAINT PK_BATCH_TEST PRIMARY KEY (ID)

)

批處理操做執行

要將記錄插入到BATCH_TEST表中,咱們使用如下SQL查詢:

1

INSERT INTO BATCH_TEST VALUES (:ID, :F_INTEGER, :F_FLOAT, :F_STRING, :F_DATE)

使用簡單插入操做時,查詢參數值以下:

UniDAC

查詢執行後,一條記錄將插入到BATCH_TEST表中。

使用批處理操做時,查詢及其參數保持不變。可是,參數值將包含在一個數組中:

UniDAC

如今,在執行查詢時,一次向表中插入5條記錄。

如何在代碼中實現批量操做?

批量插入操做樣本

讓咱們嘗試使用批插入操做將1000行插入到BATCH_TEST表中:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

var

  i: Integer;

begin

  // describe the SQL query

  UniQuery1.SQL.Text := 'INSERT INTO BATCH_TEST VALUES (:ID, :F_INTEGER, :F_FLOAT, :F_STRING, :F_DATE)';

 

  // define the parameter types passed to the query :

  UniQuery1.Params[0].DataType := ftInteger;

  UniQuery1.Params[1].DataType := ftInteger;

  UniQuery1.Params[2].DataType := ftFloat;

  UniQuery1.Params[3].DataType := ftString;

  UniQuery1.Params[4].DataType := ftDateTime;

 

  // specify the array dimension:

  UniQuery1.Params.ValueCount := 1000;

 

  // populate the array with parameter values:

  for i := 0 to UniQuery1.Params.ValueCount - 1 do begin

    UniQuery1.Params[0][i].AsInteger := i + 1;

    UniQuery1.Params[1][i].AsInteger := i + 2000 + 1;

    UniQuery1.Params[2][i].AsFloat := (i + 1) / 12;

    UniQuery1.Params[3][i].AsString := 'Values ' + IntToStr(i + 1);

    UniQuery1.Params[4][i].AsDateTime := Now;

  end;

 

  // insert 1000 rows into the BATCH_TEST table

  UniQuery1.Execute(1000);

end;

此命令將使用準備好的參數值數組,經過一個SQL查詢向表中插入1000行。還能夠將另外一個參數–偏移(默認爲0)–傳遞給方法。Offset參數指向數組元素,批處理操做從該元素開始。

咱們能夠經過兩種方式將1000條記錄插入到BATCH_TEST表中。

每次1000行:

1

UniQuery1.Execute(1000);

2×500行:

1

2

3

4

5

// insert first 500 rows

UniQuery1.Execute(500, 0);

 

// insert next 500 rows

UniQuery1.Execute(500, 500);

500行,而後是300行,最後是200行:

1

2

3

4

5

6

7

8

// insert 500 rows

UniQuery1.Execute(500, 0);

 

// insert next 300 rows starting from 500

UniQuery1.Execute(300, 500);

 

// insert next 200 rows starting from 800

UniQuery1.Execute(200, 800);

批量更新操做示例

經過批處理操做,咱們能夠修改BATCH_TEST表中的全部1000行,這很簡單:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

var

  i: Integer;

begin

  // describe the SQL query

  UniQuery1.SQL.Text := 'UPDATE BATCH_TEST SET F_INTEGER=:F_INTEGER, F_FLOAT=:F_FLOAT, F_STRING=:F_STRING, F_DATE=:F_DATE WHERE ID=:OLDID';

 

  // define parameter types passed to the query:

  UniQuery1.Params[0].DataType := ftInteger;

  UniQuery1.Params[1].DataType := ftFloat;

  UniQuery1.Params[2].DataType := ftString;

  UniQuery1.Params[3].DataType := ftDateTime;

  UniQuery1.Params[4].DataType := ftInteger;

 

  // specify the array dimension:

  UniQuery1.Params.ValueCount := 1000;

 

  // populate the array with parameter values:

  for i := 0 to 1000 - 1 do begin

    UniQuery1.Params[0][i].AsInteger := i - 2000 + 1;

    UniQuery1.Params[1][i].AsFloat := (i + 1) / 100;

    UniQuery1.Params[2][i].AsString := 'New Values ' + IntToStr(i + 1);

    UniQuery1.Params[3][i].AsDateTime := Now;

    UniQuery1.Params[4][i].AsInteger := i + 1;

  end;

 

  // update 1000 rows in the BATCH_TEST table

  UniQuery1.Execute(1000);

end;

批量刪除操做樣本

從BATCH_TEST表中刪除1000行的操做以下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

var

  i: Integer;

begin

  // describe the SQL query

  UniQuery1.SQL.Text := 'DELETE FROM BATCH_TEST WHERE ID=:ID';

 

  // define parameter types passed to the query:

  UniQuery1.Params[0].DataType := ftInteger;

 

  // specify the array dimension

  UniQuery1.Params.ValueCount := 1000;

 

  // populate the arrays with parameter values

  for i := 0 to 1000 - 1 do

    UniQuery1.Params[0][i].AsInteger := i + 1;

 

  // delete 1000 rows from the BATCH_TEST table

  UniQuery1.Execute(1000);

end;

性能比較

BATCH_TEST表示例容許使用數據庫和批處理操做分析正常操做的執行速度:

UniDAC

須要注意的是,在不一樣的數據庫服務器上修改同一個表時,檢索到的結果可能會有所不一樣。這是因爲操做執行速度可能因特定服務器的設置、其當前工做負載、吞吐量、網絡鏈接等而不一樣。

在批處理操做中訪問參數時不該該作

在填充數組和插入記錄時,咱們經過索引訪問查詢參數。更明顯的是,按名稱訪問參數:

1

2

3

4

5

6

7

for i := 0 to 9999 do begin

  UniQuery1.Params.ParamByName('ID')[i].AsInteger := i + 1;

  UniQuery1.Params.ParamByName('F_INTEGER')[i].AsInteger := i + 2000 + 1;

  UniQuery1.Params.ParamByName('F_FLOAT')[i].AsFloat := (i + 1) / 12;

  UniQuery1.Params.ParamByName('F_STRING')[i].AsString := 'Values ' + IntToStr(i + 1);

  UniQuery1.Params.ParamByName('F_DATE')[i].AsDateTime := Now;

end;

可是,參數數組的填充速度會變慢,由於在每一個循環迭代中,必須根據每一個參數的名稱定義其序號。若是循環執行10000次,性能損失可能會變得至關嚴重。

相關文章
相關標籤/搜索