PostgreSQL pgbench : 冒号处理

1 minute read

背景

pgbench 的自定义测试脚本中,冒号有特殊的含义,可以用于变量名的前面,表示这个位置使用变?刻婊弧?

        /*----------  
         * Join arguments with whitespace separators. Arguments starting with  
         * exactly one colon are treated as variables:  
         *      name - append a string "name"  
         *      :var - append a variable named 'var'  
         *      ::name - append a string ":name"  
         *----------  
         */  
        for (i = 0; i < argc; i++)  
        {  
                char       *arg;  
                int                     arglen;  
  
                if (argv[i][0] != ':')  
                {  
                        arg = argv[i];          /* a string literal */  
                }  
                else if (argv[i][1] == ':')  
                {  
                        arg = argv[i] + 1;      /* a string literal starting 
with colons */  
                }  
                else if ((arg = getVariable(st, argv[i] + 1)) == NULL)  
                {  
                        fprintf(stderr, "%s: undefined variable \"%s\"\n",  
                                        argv[0], argv[i]);  
                        return false;  
                }  
  
                arglen = strlen(arg);  
                if (len + arglen + (i > 0 ? 1 : 0) >= SHELL_COMMAND_SIZE - 1)  
                {  
                        fprintf(stderr, "%s: shell command is too long\n", 
argv[0]);  
                        return false;  
                }  
  
                if (i > 0)  
                        command[len++] = ' ';  
                memcpy(command + len, arg, arglen);  
                len += arglen;  
        }  

例如,

1、以下ab为变量名,:ab表示这个地方用变量替换。

vi test.sql  
  
\set ab random(1,100000)  
select * from tbl where id=:ab;  

2、如果要输入一个冒号开头的常量,可以输入两个冒号。

::name表示:name常量。  

3、如果在字符中间输入,两个冒号,直接输入两个冒号即可。

4、

如果要在字符串中间使用冒号,怎么写呢?

vi test.sql  
  
select * from tbl where ts > '2017-01-01 10:10:10';  

这样不行,会将:10和:10都翻译成变量10的值。

这样也不行,字符串中两个冒号就是两个冒号,不会变成一个。

vi test.sql  
  
select * from tbl where ts > '2017-01-01 10::10::10';  

冒号作为字符串中的内容

1、使用-D参数,适合所有无法正常解析customer script的场景。

使用pgbench -D参数,输入的变量,不需要过customer script的parser ,所以可以避免问题。

vi test.sql  
  
select now() > :a::timestamp;  
  
pgbench -M prepared -n -r -P 1 -f ./test.sql -c 56 -j 56 -T 120 -D a="1999-1-
1 10:1:1"  

达到的效果是

select now() > '1999-1-1 10:1:1'::timestamp;  

2、使用格式化函数,适合某些场景。

前面那条SQL可以改成

vi test.sql  
  
select now() > to_timestamp('2017-01-01 10::10::10','yyyy-mm-dd hh24::mi::ss')
;  
  
pgbench -M prepared -n -r -P 1 -f ./test.sql -c 56 -j 56 -T 120  

参考

https://www.postgresql.org/docs/10/static/pgbench.html

Flag Counter

digoal’s 大量PostgreSQL文章入口