1. 程式人生 > >使用 SQL 生成大量測試資料

使用 SQL 生成大量測試資料

無論您是在用原型證明某一概念,還是開發一個全新的應用程式,或者只是學習 SQL,您都需要在您的應用程式上執行測試資料。為了有效地測試應用程式的效能,您必須擁有足夠的測試資料,以便暴露潛在的效能問題。只要可以得到,用實際資料來進行測試總是更可取一些。如果沒有可用的實際資料,那麼在許多情況下,也可以生成足夠的假想資料。一般來說,從頭開始構造大量資料是件很容易的工作,您自己就可以快速地獨立完成。

本文提供了一些如何利用 SQL 指令碼來生成測試資料的示例,而這些指令碼本身就是較好的 SQL 實踐。並且還討論了一些為了生成儘可能真實的資料而應該注意的問題。

即使資料庫是新建立且仍然為空的,也總是會帶有系統表和檢視,因此,您可以按以下方法使用它們:

CREATE TABLE DB2ADMIN.SALES
  (CUSTOMER_ID INT NOT NULL, ITEM_ID INT NOT NULL, 
  SALE_QUANTITY SMALLINT NOT NULL, SALE_DATE DATE NOT NULL);
INSERT INTO SALES 
  SELECT 
    SYSFUN.RAND()*500 + 1 AS CUSTOMER_ID, 
    SYSFUN.RAND()*100 + 1 AS ITEM_ID,
    1 + SYSFUN.RAND()*10 AS SALE_QUANTITY, 
    DATE('01/01/2003') + (SYSFUN.RAND()*200) DAYS AS SALE_DATE
  FROM SYSCAT.COLUMNS;

SALES 表中的記錄數就與 SYSCAT.COLUMNS 中的完全一樣了。請注意,多個列都是用隨機值來填充的。例如,SALE_QUANTITY 列中的所有值都是處於 1 到 10 之間,約 10% 的記錄具有各不相同的值。如果您需要更多記錄,就可以根據需要多次重複執行這條 INSERT 語句。您還可以像下面這樣使用交叉連線(CROSS JOIN),以便每條語句獲得更多記錄:

INSERT INTO SALES 
SELECT 
SYSFUN.RAND()*500 + 1 AS CUSTOMER_ID, 
SYSFUN.RAND()*100 + 1 AS ITEM_ID,
1 + SYSFUN.RAND()*10 AS SALE_QUANTITY, 
DATE('01/01/2003') + (SYSFUN.RAND()*2000) DAYS AS SALE_DATE
FROM SYSCAT.TABLES T1 JOIN SYSCAT.TABLES T2;

注意:本例中,表 T1 和 T2 的連線是不含任何條件的,因此,T1 中的每一行會匹配 T2 中的每一行。這種型別的連線稱作交叉連線。關於交叉連線的更多資訊,請查閱 Joe Celko 的 SQL for Smarties一書。

注意:這條 INSERT 語句所涉及的事務可能會相當大,以致於您的伺服器無法加以處理。如果您遇到“log full”的情況(SQL0964C 資料庫的事務日誌已滿),您可能需要增加日誌空間,或者通過指定 T1 或 T2 或兩者中的 WHERE 子句來獲得一個較小的事務。

您可以使用該方法來生成大量記錄,然而,該方法有點過分簡單了,因為所有的值都是均勻分佈的,而且它們之間不存在相關性。

填充子表

您的資料庫中很可能存在多對一的關係。下列示例展示瞭如何填充子表,以使每一條父記錄都具有隨機的多條子記錄。

CREATE TABLE DB2ADMIN.PARENT_TABLE(PARENT_ID INT NOT NULL, NUM_CHILDREN
        
INT NOT NULL); INSERT INTO DB2ADMIN.PARENT_TABLE SELECT ROW_NUMBER() OVER(), SYSFUN.RAND()*5 + 1 FROM SYSCAT.TABLES; ALTER TABLE DB2ADMIN.PARENT_TABLE ADD PRIMARY KEY(PARENT_ID); CREATE TABLE DB2ADMIN.CHILD_TABLE(PARENT_ID INT NOT NULL, CHILD_NUM INT
NOT NULL); INSERT INTO DB2ADMIN.CHILD_TABLE SELECT PARENT_ID, SEQUENCE_TABLE.NUM FROM DB2ADMIN.PARENT_TABLE JOIN (SELECT ROW_NUMBER() OVER() AS NUM FROM SYSCAT.TABLES) AS SEQUENCE_TABLE ON AUXILIARY_TABLE.NUM<NUM_CHILDREN;

最後一條 INSERT 語句的結果是,每一條父記錄有 1 到 6 條子記錄。SEQUENCE_TABLE 是一個表表達式。關於表表達式的更多資訊,請查閱 Sheryl Larsen 的文章。




回頁首

如果一列中的某些值所出現的頻率比其他的要大很多,則該資料存在 資料傾斜(data skew)。例如:

SELECT CITY, COUNT(*) FROM CUSTOMER
GROUP BY CITY
ORDER BY COUNT(*) DESC
CHICAGO  		236
MILWAKEE		95
ROCKFORD		4
NAPERVILLE		3
SPRINGFIELD		3
(snip)
279 rows selected

每當您有理由期望在生產資料中出現數據傾斜時,您就可能需要在測試資料中再現資料傾斜,首先,在一個表中儲存預計頻率:

CREATE TABLE COLOR_FREQUENCY(COLOR CHAR(10), FREQUENCY SMALLINT);
INSERT INTO COLOR_FREQUENCY VALUES
('RED', 37), ('SILVER',12), ('AMBER', 3), ('GREEN', 3),
        
('WHITE',2),('BLACK', 1),('BLUE',1);

接著,建立一個輔助表(更明確地說,是一個序列表)。

CREATE TABLE CONSECUTIVE_NUMBER(NUM INT NOT NULL);
INSERT INTO CONSECUTIVE_NUMBER
SELECT ROW_NUMBER() OVER() AS NUM FROM SYSCAT.COLUMNS;

注意:Joe Celko 的 SQL for Smarties 一書中有一章是關於輔助表的。現在,讓我們連線這兩個表:

SELECT COLOR, FREQUENCY, NUM
FROM COLOR_FREQUENCY JOIN CONSECUTIVE_NUMBER
ON NUM BETWEEN 1 AND FREQUENCY ORDER BY FREQUENCY, COLOR;
COLOR      FREQUENCY NUM         
---------- --------- ----------- 
BLACK              1           1 
BLUE               1           1 
WHITE              2           1 
WHITE              2           2 
AMBER              3           1 
AMBER              3           2 
AMBER              3           3
(SNIP)

正如我們所看到的,COLOR_FREQUENCY 表中的每一行都連線了 CONSECUTIVE_NUMBER 表中的 FREQUENCY 行。該示例生成了您需要用於獲得所需值分佈的確切內容:

CREATE TABLE T_SHIRT(COLOR VARCHAR(30) NOT NULL, SIZE CHAR(1) NOT NULL);
INSERT INTO T_SHIRT
SELECT COLOR, 'M' AS SIZE
FROM COLOR_FREQUENCY JOIN CONSECUTIVE_NUMBER
ON NUM BETWEEN 1 AND FREQUENCY;
SELECT COLOR, COUNT(*) FROM T_SHIRT GROUP BY COLOR;
COLOR                          2           
------------------------------ ----------- 
AMBER                                    3 
BLACK                                    1 
BLUE                                     1 
GREEN                                    3 
RED                                     37 
SILVER                                  12 
WHITE                                    2 ;

因此,T_SHIRT 表現在有 37+12+3+3+2+1+1 = 57 行。該表剛好具有所需的值分佈。

使用前一章中的所用表,您還可以為 SIZE 列指定值分佈:

CREATE TABLE SIZE_FREQUENCY(SIZE CHAR(1), FREQUENCY SMALLINT);
INSERT INTO SIZE_FREQUENCY VALUES
('S', 5), ('M',7), ('L', 9);
			

並使用兩個表表達式來填充 T_SHIRT 表:

INSERT INTO T_SHIRT
SELECT COLOR, SIZE
FROM 
(SELECT COLOR FROM COLOR_FREQUENCY JOIN CONSECUTIVE_NUMBER ON NUM
        
BETWEEN 1 AND FREQUENCY) C, (SELECT SIZE FROM SIZE_FREQUENCY JOIN CONSECUTIVE_NUMBER ON NUM BETWEEN
1 AND FREQUENCY) S

第一個表表達式產生 57 行,而第二個表表達式則產生 5+7+9=21 行。由於我們沒有指定任何連線條件,所以第一個結果集中的每一行將會連線第二個中的每一行,從而產生 57*21 行。

注意:交叉連線可能會生成太多行。因此,該事務將太大,以致伺服器無法處理。本例中,您可能需要幾個較小一些的 INSERT 語句,例如在第一個 INSERT 中使用以下表表示式:

(SELECT SIZE FROM SIZE_FREQUENCY JOIN CONSECUTIVE_NUMBER ON NUM BETWEEN
        
1 AND FREQUENCY AND SIZE='L') S

並且在第二個 INSERT 語句中將這個表表達式修改為:

(SELECT SIZE FROM SIZE_FREQUENCY JOIN CONSECUTIVE_NUMBER ON NUM BETWEEN
        
1 AND FREQUENCY AND SIZE<>'L') S

假定我們需要生成幾行記錄來填充 CAR 表:

CREATE TABLE CAR(
MAKE VARCHAR(20) NOT NULL,
MODEL VARCHAR(20) NOT NULL,
OTHER_DATA VARCHAR(20));
			

如果嘗試前一章中的方法,我們最後將獲得一些不可能的 MAKE/MODEL 組合,例如“TOYOTA METRO”和“GEO CAMRY”。該狀況稱作 MAKE 列和 MODEL 列之間的相關性。正確的方法是指定有效對(MAKE,MODEL)及其頻率:

CREATE TABLE MAKE_MODEL_FREQUENCY(MAKE VARCHAR(20), MODEL VARCHAR(20),
        
FREQUENCY SMALLINT); INSERT INTO MAKE_MODEL_FREQUENCY VALUES ('TOYOTA','CAMRY', 40), ('HONDA','ACCORD',40), ('CHEVY', 'PRIZM', 5),
('GEO','PRIZM', 5), ('CHEVY', 'METRO', 5), ('GEO', 'METRO', 10);

一旦完成該工作,我們就可以按照前面一模一樣的方法來連線 CONSECUTIVE_NUMBER 和 MAKE_MODEL_FREQUENCY 表了。




回頁首

表的物理行次序將影響該表上幾乎所有查詢的效能。因此,所生成的資料具有理想的物理行次序是極其重要的。如果您期望一個索引具有較高的群集因子,就只要重組該索引上的表。相反,如果您期望該索引具有較低的群集因子,也可以容易地以隨機次序來打亂該表的次序,從而使得該索引的群集因子接近於 0:

CREATE TABLE  NAMES(
FULL_NAME VARCHAR(50)  NOT NULL,
ORDERED_ON INT);
INSERT INTO NAMES(FULL_NAME, ORDERED_ON)
SELECT TABNAME || ', ' || COLNAME AS FULL_NAME, 
SYSFUN.RAND() * 10000 AS ORDERED_ON
FROM SYSCAT.COLUMNS;
CREATE INDEX NAMES_FULL_NAME ON NAMES(FULL_NAME);
CREATE INDEX NAMES_ORDER ON NAMES(ORDERED_ON);
REORG TABLE DB2ADMIN.NAMES INDEX DB2ADMIN.NAMES_ORDER;
RUNSTATS ON TABLE DB2ADMIN.NAMES AND DETAILED INDEXES ALL;

在進行重組之後,索引 NAMES_FULL_NAME 將具有一個極低的群集因子(接近於 0),因為現在的行是以隨機次序儲存的。

注意:還可以重組該表,以使索引 NAMES_FULL_NAME 的群集因子接近 0 到 1 之間的任何給定值,但是,該內容超出了本文的範圍。

相關推薦

使用 SQL 生成大量測試資料

無論您是在用原型證明某一概念,還是開發一個全新的應用程式,或者只是學習 SQL,您都需要在您的應用程式上執行測試資料。為了有效地測試應用程式的效能,您必須擁有足夠的測試資料,以便暴露潛在的效能問題。只要可以得到,用實際資料來進行測試總是更可取一些。如果沒有可用的實際資料,那麼

Oracle生成大量測試資料的方法

Oracle生成一百萬測試資料的方法如下: 方法一:建立一個表,並同時新增1000000條資料,程式碼: create table TestTable as    select rownum as id,                  to_char(sy

Oracle快速生成大量測試資料

最近有個小模組,是在災備機之間拷貝備份資料,同時把相關的資料表也拷貝到目標系統上。 這裡涉及到一個問題:Oracle表空間達到上限之後怎麼處理? 一般來說,將表空間設定為自增,不限制最大容量可以滿足大部分需求。但是,即便是表空間不設定上限,資料檔案的大小也是會有最大值的,

sql生成隨機測試資料

利用sql語句產生隨機測試資料 詳細程式碼如下 create database test; use test; drop table if exists `card` ; CREATE TABLE `card` ( `card_id` bigint(20) NOT NULL

oracle索引 & 快速生成大量測試資料

1.建立索引 create index <index_name> on <table_name>(<colnum_name>) [tablespace <tablespace_name>] 2.刪除索引 drop index

隨機生成萬分測試資料

DROP TABLE IF EXISTS `vote_record_memory`; CREATE TABLE `vote_record_memory` (     `id` int(10) unsigned NOT NULL AUTO_INCREMENT,   &

SQL批量插入測試資料

方法一:直接使用insert into...select...方法 CREATE TABLE test( id int ); --count表示插入的次數 insert into test

.NET使用Bogus生成大量隨機資料

.NET如何生成大量隨機資料 在演示Demo、資料庫脫敏、效能測試中,有時需要生成大量隨機資料。Bogus就是.NET中優秀的高效能、合理、支援多語言的隨機資料生成庫。 Bogus的Github連結:https://github.com/bchavez/Bogus,圖示如下: 安裝Bogus 目前Bogu

一條SQL快速生成大量測試資料

Oracle幾個小技巧: 1、利用Oracle特有的“connect by”樹形連線語法生成測試記錄,“level <= 10”表示要生成10記錄; 2、利用rownum虛擬列生成遞增的整數資料; 3、利用sysdate函式加一些簡單運算來生成日期資料,本例中是每條記錄的時間加1秒; 4、利用dbms_

生成大量測試資料的三種方法,1寫sql,2工具plsql,3LoadRunner

效能測試場景之一: [1]03 臨時表裡有20W記錄,傳送ESB 說明:結算後臺對完賬後,在對賬彙總確認選單中點“確認”按鈕,系統會將已清算的資料資訊插入資金庫的臨時表pac_biz_account_histmp中,然後逐步esb傳送給物流訂單系統進行分潤處理。 一 通過工

Postgresql 隨機生成測試資料sql

100w條隨機測試資料。 create table abc (a integer,b integer,c integer ,d integer); postgres=# insert into a

Oracle中如何用一條SQL快速生成10萬條測試資料

SQL> select rownum as id,  2     to_char(sysdate + rownum / 24 / 3600, 'yyyy-mm-dd hh24:mi:ss') as inc_datetime,  3     trunc(dbms_random.value(0, 100))

Sql Server生成測試資料

GO create table tb_TestTable400 --建立表 ( id int identity(1,1) primary key, userName nvarchar(40)

使用sql語句生成測試資料

做資料庫開發或管理的人經常要建立大量的測試資料,動不動就需要上萬條,如果一條一條的錄入,那會浪費大量的時間,本文介紹了Oracle中如何通過一條SQL快速生成大量的測試資料的方法。 產生測試資料的SQL如下: SQL> select rownum as id, 2

Oracle中如何用一條SQL快速生成10萬條測試資料(轉)

做資料庫開發或管理的人經常要建立大量的測試資料,動不動就需要上萬條,如果一條一條的錄入,那會浪費大量的時間,本文介紹了Oracle中如何通過一條SQL快速生成大量的測試資料的方法。產生測試資料的SQL如下:SQL> select rownum as id, 2

如何一條SQL快速生成100萬條測試資料

SQL> select rownum as id,  2                 to_char(sysdate + rownum / 24 / 3600, 'yyyy-mm-dd hh24:mi:ss') as inc_datetime,  3                 trunc(db

oracle一句sql生成10w行測試資料

-- 'u', 'U' - 返回全是大寫的字串 -- 'l', 'L' - 返回全是小寫的字串 -- 'a', 'A' - 返回大小寫結合的字串 -- 'x', 'X' - 返回全是大寫和數字的字串 -- 'p', 'P' - 返回鍵盤上出現字元的隨機組合 create

藉助資料庫執行sql語句批量生成測試資料

本人在學習selenium2java和資料庫使用的過程中,需要測試兌換卡購買課程的功能。測試的兌換卡之前都是手動新增的比較麻煩,自己寫了一個方法,批量生成測試兌換卡。 //新增兌換卡 public static void addCoupon() throws Class

使用 SQL Data Generator 4 生成測試資料

首先我們開啟軟體,它會彈出新增資料庫的操作介面,如圖: 新增資料庫這裡我們不做過多的講解。 接下來是對錶的設定。 接下來我們可以對列進行這些設定: 這裡挑幾個典型的說一下: 這是使用正則表示式限制生成的測試資料。 這是對日期的設定。 除此

論文:基於粒子群優化的測試資料生成及其實證分析-----生成過程以及實驗(計算機研究與發展)

來源:2012年版的計算機研究與發展期刊 基於PSO的測試資料生成 (1) 核心問題:  如何保證PSO搜尋演算法和測試過程的協作執行  演算法的基本的流程: (1)對被測程式P進行靜態分析並完成: 1.  提取程式的 介面資