注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

星期五

明天不上班

 
 
 

日志

 
 
关于我

一个特立独行的Java程序员,比较宅,上上网,写博客,听音乐,看电影。

网易考拉推荐

PostgreSQL 之 生成测试数据  

2011-07-11 23:53:51|  分类: Postgresql |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

开发人员为了测试SQL语句的性能,就非常有必要生成一些假数据

针对Postgresql

生成序列

SELECT * FROM generate_series(1,5);

生成date

SELECT date(generate_series(now(), now() + '1 week', '1 day'));

生成integer 随机数
SELECT (random()*(2*10^9))::integer;
生成numeric 随机数
random()*100.)::numeric(4,2)
生成字符串
substr('abcdefghijklmnopqrstuvwxyz',1, (random()*26)::integer)
生成重复串
repeat('1',(random()*40)::integer)

举例:

SELECT generate_series(1,10) as key,(random()*100.)::numeric(4,2),repeat('1',(random()*25)::integer) ORDER BY random();

postgres=# SELECT generate_series(1,10) as key,(random()*100.)::numeric(4,2),repeat('1',(random()*25)::integer) ORDER BY random();
 key | numeric |         repeat          
-----+---------+-------------------------
   6 |   67.98 | 1111111111111111
   4 |   48.85 | 111
   5 |   57.71 | 1111111111111111111111
   7 |    8.05 | 111111111111111111111
   2 |   27.97 | 11111111111111111111111
   9 |   22.14 | 1111111111111111
   3 |   29.36 | 1111111111111111111
   8 |   55.99 | 1111111111
   1 |   86.20 | 
  10 |    7.52 | 11111111111111
(10 行记录)

看了上面数据的生成方式,我认为有必要写一个Function去做这些事

------------------------------------------------------------------------------------------------------------------------

--参数是 生成的行数 和 表名

?CREATE OR REPLACE FUNCTION generate_test_data(IN num integer, IN table_name text) 
RETURNS void AS
$$
DECLARE
query_sql text :='';
insert_sql text :='';
insert_sql_1 text :='';
insert_sql_2 text :='';
column_info record;
type_name name :='';
column_name name :=''; 

BEGIN

       -- 根据表名查出各列的类型和列名

        query_sql := 'select t.typname as type, a.attname as name
from pg_class c, pg_attribute a, pg_type t
where c.relname = '''|| table_name ||''' and a.attnum > 0 
and a.attrelid = c.oid and a.atttypid = t.oid';
       --组成插入语句
        insert_sql_1 := 'insert into '||table_name||'(';

        insert_sql_2 := 'values(';
        
        for column_info in execute(query_sql) loop
                
                type_name := column_info.type;
                column_name := column_info.name;
                --根据类型写表达式拼insert语句  
if substring(type_name from 1 for 3) = 'int' then
insert_sql_1 := insert_sql_1 || column_name ||',';
insert_sql_2 := insert_sql_2 || '(random()*(2*10^9))::integer' ||',';
elsif type_name = 'text' then
insert_sql_1 := insert_sql_1 || column_name ||',';
insert_sql_2 := insert_sql_2 || 'substr(''abcdefghijklmnopqrstuvwxyz'',1, (random()*26)::integer)'||',';
elsif type_name = 'char' then
insert_sql_1 := insert_sql_1 || column_name ||',';
insert_sql_2 := insert_sql_2 || 'substr(''abcdefghijklmnopqrstuvwxyz'',1, (random()*26)::integer)::char'||',';
elsif substring(type_name from 1 for 5) = 'float' then
insert_sql_1 := insert_sql_1 || column_name ||',';
insert_sql_2 := insert_sql_2 || '(random()*(2*10^9))::float' ||',';
elsif type_name = 'varchar' then
insert_sql_1 := insert_sql_1 || column_name ||',';
insert_sql_2 := insert_sql_2 || 'substr(''abcdefghijklmnopqrstuvwxyz'',1, (random()*26)::integer)'||',';
elsif type_name = 'date' then
insert_sql_1 := insert_sql_1 || column_name ||',';
insert_sql_2 := insert_sql_2 || 'date(generate_series(now(), now() + ''1 week'', ''1 day''))' ||',';
elsif type_name = 'time' then
insert_sql_1 := insert_sql_1 || column_name ||',';
insert_sql_2 := insert_sql_2 || 'generate_series(now(), now() + ''1 week'', ''1 day'')::time' ||',';
elsif type_name = 'timestamp' then
insert_sql_1 := insert_sql_1 || column_name ||',';
insert_sql_2 := insert_sql_2 || 'generate_series(now(), now() + ''1 week'', ''1 day'')::timestamp' ||',';
                end if;

        end loop;

       --insert语句生成OK

        insert_sql_1 := substring(insert_sql_1 from 1 for char_length(insert_sql_1)-1)||')';
        insert_sql_2 := substring(insert_sql_2 from 1 for char_length(insert_sql_2)-1)||')';
        insert_sql := insert_sql_1 ||' '||insert_sql_2;
        --raise notice '%',insert_sql;

        for i in 1..num loop

       --执行insert语句

        --raise notice '%',i;
execute(insert_sql);
        end loop;
END;
$$
LANGUAGE 'plpgsql';
--------------------------------------------------------------------------------------------------------------------------------

看测试结果

select generate_test_data(10,'test');

  PostgreSQL 之 生成测试数据 - zhenghaoju700 - zhenghaoju700 的博客
看生成的数据

  PostgreSQL 之 生成测试数据 - zhenghaoju700 - zhenghaoju700 的博客
发现了一个问题我输入的是10 为什么生成了80条数据?

总之这个函数还需要改进,不过目前够用。


默认情况下, postgresql的SQL语句,每条都是一个事务,

除非用start transaction手工开启一个事务,直到commit(rollback)结束一个事务.

插入800万条数据

start transaction;

select generate_test_data(1000000,'test');

commit;

 

参考资料

http://bbs.pgsqldb.com/index.php?t=msg&th=11928&rid=&S=458852aed5a3538ff5cc19cac3c59677&pl_view=&start=0#msg_48435

  评论这张
 
阅读(596)| 评论(0)
推荐

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017