如何生成比較像樣的假資料

2021-05-23 00:12:15 字數 2960 閱讀 7867

問題

在做專案的時候經常會遇到這樣的問題:

方案

其中要生成大量的沒有意義的測試資料,以便進行壓力測試,這個資料是最好生成的,只需要寫幾條sql語句,多執行幾次即可。如果不想寫sql語句,也可以使用資料生成工具:visualstudio、powerdesigner、datafactory等都可以使用。我推薦使用datafactory,有較強的定製性。

下面主要說一下另外一種假資料,那就是前面2種情況,具有一定業務規則和可讀性的假資料。要生成比較像樣的假資料主要是基於已有的系統,在真實資料的基礎上進行隨機的混淆和交叉,從而產生大量看起來比較真實但是實際上卻全是假的資料。對於第一種情況,可以將其他系統中的對應實體表的資料匯入到demo環境中,然後再進行混淆交叉。

我們可以將系統中的資料分為:數字、日期和字串3種型別分別進行混淆。

數字型別的資料混淆最簡單,使用隨機函式rand()即可,如果是整數則可以再乘以乙個係數後取整,也可以用原來的資料加上生成的隨機數,從而使得資料的範圍保持在原真實資料相同的分布。比如有revenue欄位,是從客戶處的收入,大客戶和小客戶引數的收入數不能完全隨機,可以在原有revenue的基礎上隨機增加10000以內的數即可:revenue+rand()*10000

日期型別的資料混淆可以在原日期或者當前日期的基礎上加減乙個隨機的天數形成,使用dateadd()函式和rand()函式即可。比如生成隨機的最近100天內的日期:dateadd("day",0-rand()*100,getdate())

字串型別的資料混淆最為複雜,因為字串具有很明確的意義,比如名字字段、公司名字段等,如果隨機的生成字元將沒有任何意義。這時可以考慮將字串拆分成兩部分然後進行交叉組合,用隨機的交叉組合來代替真是的資料。比如原來的姓名是:李宇春、曾軼可、劉著,經過交叉組合就會形成:李著、曾宇春、劉軼可之類的組合。

姓名的拆分是分為姓和名,而公司的拆分可以拆分成前2個字和後面的字。如果是英文姓名或者英文公司名則可以按照第乙個空格將英文本串拆分成第乙個單詞和後面的單詞。然後將產生的兩個字段存入臨時表,用兩個臨時表進行交叉聯接,得到兩個欄位的所有組合,然後再隨機選出一定條數的資料,用選出的隨機資料將原有資料替換即可。

示例

以乙個hr系統為例。假設其中有乙個employee表,該錶記錄了員工的工號、姓名等資訊,現在要對姓名進行處理,具體操作如下:

1.區分出中文名和英文名,分別進行拆分。中文姓名以第乙個字為a列,剩下的字尾b列,英文名以第乙個單詞為a列,剩下的單詞為b列,將拆分的資料存入臨時表,具體sql語句如下:

select substring(name,1,1) a,substring(name,2,10) b into #cname

from employee

where unicode( name)>255 --中文

select name,substring(name,1,charindex(' ',name,1)) a,substring(name,charindex(' ',name,1),50) b into #ename

from employee

where unicode( name)<255 --英文

2.讓a列和b列進行交叉聯接,得到姓名組合的全集,然後隨機選出與源資料相同資料量的姓名存入臨時表(臨時表中有id流水號字段)。假設員工表裡有5000員工資料,則可以選取5000個隨機姓名,**如下:

create table #newcname(id int identity primary key,name nvarchar(50))

insert into #newcname(name)

select top 5000 n1.a+n2.b

from #cname n1

cross join #cname n2

order by newid() --隨機選取行

3.由於employee中沒有自增的id欄位,只有字串形式的員工號作為主鍵,所以需要給每個員工號編乙個流水號,用於和隨機姓名中的流水號對應,以便接下來的update操作:

create table #newemployeeid(id int identity primary key,employeeid varchar(10))

insert into #newemployeeid

select employeeid

from employee

where unicode( name)>255 --中文

4.更新employee表中的姓名欄位為隨機生成的姓名:

update employee

set name=n.name

from employee e

inner join #newemployeeid i

on e.employeeid=i.employeeid

inner join #newcname n

on i.id=n.id

where unicode(e.name)>255 --只更新中文姓名

5.用同樣的方法,可以對英文姓名進行混淆交叉替換。

優化

這裡需要注意的是第2步,使用了cross join操作,也就是求兩個表的笛卡爾積,如果乙個表中有10w條資料,那麼將會產生100億行結果,然後再進行排序,那將是近乎不可能完成的任務,所以必須減少進行笛卡爾積的表的資料量,比如每個表只取500條不重複的資料,那麼修改後的sql語句是:

select top 5000 n1.a+n2.b

from

(select distinct top 500 a from #cname )n1 --取不重複的500個姓

cross join

(select distinct top 500 b from #cname ) n2--取不重複的500個名

order by newid() --隨機選取行

這樣最多只是500*500條記錄,進行排序選取隨機行將會很快完成。

如何生成比較像樣的假資料

問題 在做專案的時候經常會遇到這樣的問題 方案 其中要生成大量的沒有意義的測試資料,以便進行壓力測試,這個資料是最好生成的,只需要寫幾條sql語句,多執行幾次即可。如果不想寫sql語句,也可以使用資料生成工具 visualstudio powerdesigner datafactory等都可以使用。...

如何生成比較像樣的假資料

問題 在做專案的時候經常會遇到這樣的問題 方案 其中要生成大量的沒有意義的測試資料,以便進行壓力測試,這個資料是最好生成的,只需要寫幾條sql語句,多執行幾次即可。如果不想寫sql語句,也可以使用資料生成工具 visualstudio powerdesigner datafactory等都可以使用。...

如何生成比較像樣的假資料 收藏

在做專案的時候經常會遇到這樣的問題 方案 其中要生成大量的沒有意義的測試資料,以便進行壓力測試,這個資料是最好生成的,只需要寫幾條sql語句,多執行幾次即可。如果不想寫sql語句,也可以使用資料生成工具 visualstudio powerdesigner datafactory等都可以使用。我推薦...