开发过程中进行很多测试,经常需要生成字符串,尝试之后选择了自己实现。
1、办法一
rpad('string ', 20000, 'x')
插入几万条之后会发现 toast 表没啥变化,因为这样子的字符串一压缩就剩不下什么了。
更多相关事宜请翻阅 TOAST 介绍
2、办法二,一个PL/pgSQL函数
来源:How do you create a random string that's suitable for a session ID in PostgreSQL?
flying=# insert into p
select pg_backend_pid(),s,'string '||random_string(20000) from (select generate_series(2000,8000,1) s) as g;
INSERT 0 6001
Time: 245627.624 ms (04:05.628)
这效率能不能接受呢
3、方法三,上边连接中提到的 string_agg
看起来似乎没有问题
批量执行
flying=# select s,(SELECT string_agg
(substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', ceil (random() * 62)::integer, 1), '') FROM generate_series(1, 20))
flying-# from (select generate_series(2,8,1) s) as g;
s | string_agg
---+----------------------
2 | WZoIDcEkOntinX4dC6uz
3 | WZoIDcEkOntinX4dC6uz
4 | WZoIDcEkOntinX4dC6uz
5 | WZoIDcEkOntinX4dC6uz
6 | WZoIDcEkOntinX4dC6uz
7 | WZoIDcEkOntinX4dC6uz
8 | WZoIDcEkOntinX4dC6uz
(7 rows)
Time: 1.069 ms
发生了什么?不过有些场景也可以接受
4、方法四,C语言实现
执行
flying=# insert into p
select pg_backend_pid(),s,'string '||random_string(20000) from (select generate_series(2000,8000,1) s) as g;
INSERT 0 6001
Time: 6774.829 ms (00:06.775)
这是一个可接受的时间
代码(未经严格测试,仅供参考)
PG_FUNCTION_INFO_V1(random_string);
Datum
random_string(PG_FUNCTION_ARGS)
{
int32 length = PG_GETARG_INT32(0);
int32 i;
const char chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char *result;
if (length < 0)
PG_RETURN_NULL();
if (length == 0)
PG_RETURN_TEXT_P(cstring_to_text(""));
result = palloc(length + 1);
if (result == NULL)
ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
for (i=0; i<length; i++)
{
result[i] = chars[random()%(sizeof(chars)-1)];
}
result[i] = '\0';
PG_RETURN_TEXT_P(cstring_to_text(result));
}
欢迎关注我司公众号:postgresdata-news
--------------------------------------------
神州飞象(北京)数据科技有限公司
我们的力量源自最先进的开源数据库PostgreSQL
zongliang.quan@postgresdata.com