2011-02-14 67 views
4

我目前在PostgreSQL中使用这个JSON转义函数作为未来原生JSON支持的一个支持。虽然它有效,但它也限制了我们的系统性能。我怎样才能优化它?也许某种查询数组?在PostgreSQL 9.0中优化转义JSON

CREATE OR REPLACE FUNCTION escape_json(i_text TEXT) 
RETURNS TEXT AS 
$body$             
DECLARE 
    idx INTEGER; 
    text_len INTEGER; 
    cur_char_unicode INTEGER; 
    rtn_value TEXT := i_text; 
BEGIN 
    -- $Rev: $ -- 
    text_len = LENGTH(rtn_value); 
    idx = 1; 

    WHILE (idx <= text_len) LOOP 
    cur_char_unicode = ASCII(SUBSTR(rtn_value, idx, 1)); 

    IF cur_char_unicode > 255 THEN 
     rtn_value = OVERLAY(rtn_value PLACING (E'\\u' || LPAD(UPPER(TO_HEX(cur_char_unicode)),4,'0')) FROM idx FOR 1); 
     idx = idx + 5; 
     text_len = text_len + 5; 
    ELSE 
     /* is the current character one of the following: " \/bs ff nl cr tab */ 
     IF cur_char_unicode IN (34, 92, 47, 8, 12, 10, 13, 9) THEN 
     rtn_value = OVERLAY(rtn_value PLACING (E'\\' || (CASE cur_char_unicode 
                 WHEN 34 THEN '"' 
                 WHEN 92 THEN E'\\' 
                 WHEN 47 THEN '/' 
                 WHEN 8 THEN 'b' 
                 WHEN 12 THEN 'f' 
                 WHEN 10 THEN 'n' 
                 WHEN 13 THEN 'r' 
                 WHEN 9 THEN 't' 
                  END) 
             ) 
           FROM idx FOR 1); 

     idx = idx + 1; 
     text_len = text_len + 1; 
     END IF; 
    END IF; 

    idx = idx + 1; 
    END LOOP;     

    RETURN rtn_value; 
END; 
$body$ 
LANGUAGE plpgsql; 

回答

5

我所有的方法归结为“做一些其他的方式”:

  • 写在其他一些语言,例如使用PL/Perl里,PL /蟒蛇,PL /红宝石
  • 编写一个包装圆C语言编写的
  • 一些外部的JSON库做的JSON逃脱在客户端,而不是在查询中(假设你的客户有一些很好的JSON逃脱支持)

在我的经验,PL/pgSQL的并不快,在这种东西─它的强度是与数据库进行数据交换,而不是作为一个通用的编程语言,它的整体支撑。

例子:

create or replace function escape_json_perl(text) returns text 
    strict immutable 
    language plperlu as $$ 
    use JSON; 
    return JSON->new->allow_nonref->encode($_[0]); 
    $$; 

简单的测试表明,这是15倍比PLPGSQL函数更快(虽然它返回围绕价值的报价,你可能想去掉)

+0

我很害怕那个。我只是编码我沉重的存储过程在python中,直到他们发布9.1 – gradbot 2011-02-15 17:59:06

6

的顺序忏悔:我是Google Summer of Code 2010的学生,他将尝试为PostgreSQL 9.1带来JSON支持。虽然我的代码功能完备,但并没有完全准备好上游,而PostgreSQL开发社区正在寻找一些替代实现。然而,随着春假的到来,我希望完成我的重写,并在本周给予最后的推动。

与此同时,您可以下载并安装work-in-progress JSON data type module,它应该在PostgreSQL 8.4.0及更高版本上运行。它是一个PGXS模块,所以你可以编译和安装它,而无需编译所有的PostgreSQL。但是,您将需要PostgreSQL服务器开发头文件。

安装是这样的:

git clone git://git.postgresql.org/git/json-datatype.git 
cd json-datatype/ 
USE_PGXS=1 make 
sudo USE_PGXS=1 make install 
psql -f json.sql <DBNAME1> # requires database superuser privileges 

尽管构建和安装只需要进行一次,json.sql需要您计划使用的JSON数据类型上的每个数据库上运行。

安装好之后,你就可以执行:

=> SELECT to_json(E'"quotes and \n newlines"\n'::TEXT); 
      to_json    
-------------------------------- 
"\"quotes and \n newlines\"\n" 
(1 row) 

请注意,这并不逃避非ASCII字符。