Chapter 15 PL/Python 语言扩展

Chapter 15 PL/Python 语言扩展

This sectioncontains an overview of the Greenplum Database PL/Python Language.

•    About Greenplum PL/Python

•    Enabling and Removing PL/Python support

•    Developing Functions with PL/Python

•    Installing Python Modules

•    示例

•    References


 


About Greenplum PL/Python

PL/Python是一种可加载的过程语言。 通过使用Greenplum数据库PL/Python扩展,您可以使用Python编写Greenplum数据库用户定义的函数,以利用Python特性和模块快速构建强大的数据库应用程序。

Greenplum数据库PL/Python扩展默认安装在Greenplum数据库中。 Greenplum数据库安装了Python和PL/Python版本。 这是Greenplum数据库使用的Python安装的位置:

$GPHOME/ext/python/

Greenplum Database PL/Python Limitations

Greenplum数据库不支持PL/Python触发器。

PL/Python仅作为Greenplum数据库不可信语言提供。

Enabling and Removing PL/Pythonsupport

PL/Python语言与Greenplum数据库一起安装。 要在数据库中创建和运行PL \ Python用户定义函数(UDF),必须在数据库中注册PL \ Python语言。

Enabling PL/Python Support

对于需要使用的每个数据库,请使用SQL命令CREATELANGUAGE或Greenplum数据库实用程序createlang注册PL/Python语言。 例如,以gpadmin系统用户身份运行此命令为数据库testdb注册PL/Python:

$ createlang plpythonu -d testdb

PL/Python被注册为不可信的语言。

Removing PL/Python Support

对于不需要PL/Python语言的数据库,使用SQL命令DROP LANGUAGE或GreenplumDatabase droplang实用程序删除对PL/Python的支持。 例如,运行此命令以gpadmin系统用户身份从数据库testdb中删除对PL/Python的支持:

$ droplangplpythonu -d testdb

当你移除对PL/Python的支持时,你在数据库中创建的PL/Python用户定义函数将不再起作用。

Developing Functions with PL/Python

PL/Python用户定义函数的主体是一个Python脚本。 当函数被调用时,它的参数作为数组args []的元素传递。 命名参数也作为普通变量传递给Python脚本。 返回语句返回PL/Python函数的结果,如果是结果集语句,则返回yield语句。

Greenplum数据库PL/Python语言模块导入Python模块pipy。 模块pipy实现这些功能:

•执行SQL查询和为查询准备执行计划的函数。

plpy.execute

plpy.prepare

•    Functions tomanage errors and messages.

plpy.debug

plpy.log

plpy.info

plpy.notice

plpy.warning

plpy.error

plpy.fatal

plpy.debug

Executing and Preparing SQL Queries

PL/Pythonpipy模块提供了两个Python函数来执行SQL查询并为查询准备一个执行计划plpy.execute和plpy.prepare。 如果从多个Python函数运行查询,则为查询准备执行计划很有用。

plpy.execute

使用查询字符串和可选的限制参数调用plpy.execute将导致查询运行,并将结果返回到Python结果对象中。 结果对象模拟一个列表或字典对象。 在结果对象中返回的行可以通过行号和列名访问。 结果集行编号从0(零)开始。 结果对象可以被修改。 结果对象有这些额外的方法:

•返回查询返回的行数的nrows。

•状态,即SPI_execute()返回值。

例如,这个PL/Python用户定义函数中的Python语句执行查询。

rv =plpy.execute("SELECT * FROM my_table", 5)

plpy.execute函数最多从my_table返回5行。 结果集存储在rv对象中。 如果my_table有一个列my_column,它将被访问为:

my_col_data= rv[i]["my_column"]

由于该函数最多返回5行,因此索引i可以是0到4之间的整数。

plpy.prepare

函数plpy.prepare为查询准备执行计划。它被称为一个查询字符串和一个参数类型列表,如果在查询中有参数引用。例如,这个声明可以在PL/Python用户定义函数中:

plan = plpy.prepare("SELECT last_name FROM my_users WHERE

first_name = $1", [ "text" ])

字符串文本是为变量$ 1传递的变量的数据类型。准备好了之后声明,您使用函数plpy.execute运行它:

rv = plpy.execute(plan, ["Fred" ], 5)

第三个参数是返回行数的限制,并且是可选的。

当您使用PL/Python模块准备执行计划时,计划将自动保存。有关执行计划的信息,请参阅PostgresServer编程接口(SPI)文档

http://www.postgresql.org/docs/8.2/static/spi.html。

为了有效地使用跨功能调用保存的计划,可以使用Python持久存储字典SD或GD之一。

全局字典SD可用于在函数调用之间存储数据。这个变量是私有的静态数据。全局字典GD是公共数据,可用于会话中的所有Python函数。小心使用GD。

每个函数在Python解释器中都有自己的执行环境,所以myfunc2中的全局数据和函数参数不可用。 如前所述,GD字典中的数据是例外。

这个例子使用SD字典:

 

CREATEFUNCTION usesavedplan() RETURNS trigger AS $$

ifSD.has_key("plan"):

plan = SD["plan"]

else:

plan =plpy.prepare("SELECT 1")

SD["plan"]= plan

# rest offunction

$$ LANGUAGEplpythonu;

 

Handling Python Errors and Messages

消息函数plpy.error和plpy.fatal引发一个Python异常,如果未被捕获,则传播到调用查询,导致当前事务或子事务被中止。函数会引发plpy.ERROR(msg),并引发plpy.FATAL msg),分别相当于调用plpy.error和plpy.fatal。其他消息功能只生成不同优先级的消息。

是否向客户端报告特定优先级的消息,请参阅“Greenplum数据库参考指南”。

 

 

Using the dictionary GD To Improve PL/PythonPerformance

在性能方面,导入一个Python模块是一个昂贵的操作,可能会影响性能。 如果频繁导入相同的模块,则可以使用Python全局变量在第一次调用时加载模块,而不需要在后续调用时导入模块。 下面的PL/Python函数使用GD持久性存储字典来避免导入一个已经被导入并且在GD中的模块。

 

psql=#

CREATEFUNCTION pytest() returns text as $$

    if 'mymodule' not in GD:

    import mymodule

    GD['mymodule'] = mymodule

  return GD['mymodule'].sumd([1,2,3])

$$;

 

 

 


Installing Python Modules

在Greenplum数据库上安装Python模块时,Greenplum数据库Python环境必须将该模块添加到群集中的所有段主机和镜像主机上。在扩展Greenplum数据库时,必须将Python模块添加到新的段主机。您可以在Greenplum数据库主机上使用Greenplum数据库实用程序gpssh和gpscp运行命令,并将文件复制到主机。有关这些实用程序的信息,请参阅Greenplum数据库实用程序指南。

作为Greenplum数据库安装的一部分,gpadmin用户环境被配置为使用与Greenplum数据库一起安装的Python。

要检查Python环境,可以使用which命令:

which python

该命令返回Python安装的位置。与Greenplum数据库一起安装的Python位于GreenplumDatabase ext/python目录中。

/path_to_greenplum-db/ext/python/bin/python

如果您正在构建Python模块,则必须确保构建版本创建了正确的可执行文件。例如,在Linux系统上,构建应创建一个64位可执行文件。

在构建要安装的Python模块之前,请确保已经安装并正确配置了用于构建模块的相应软件。构建环境仅在构建模块的主机上需要。

这些是安装和测试Python模块的示例:

•简单的Python模块安装示例(setuptools)

•复杂的Python安装示例(NumPy)

•测试已安装的Python模块

Simple Python Module Installation Example(setuptools)

本示例手动安装Python PackageIndex存储库中的Pythonsetuptools模块。该模块可让您轻松下载,构建,安装,升级和卸载Python软件包。

这个例子首先从一个包中构建模块,然后将模块安装在一个主机上。然后模块被构建并安装在段主机上。

1.从Python包索引站点获取模块包。例如,作为gpadmin用户在Greenplum数据库主机上运行这个wget命令来获取tar文件。

wget--no-check-certificatehttps://pypi.python.org/packages/source/s/setuptools/setuptools-18.4.tar.gz

2.从tar文件中提取文件。

tar -xzvfdistribute-0.6.21.tar.gz

3.转到包含软件包文件的目录并运行Python脚本来构建和安装Python软件包。

cdsetuptools-18.4

pythonsetup.py build && python setup.py install

4.如果模块对Python可用,则以下Python命令不会返回错误。

python -c"import setuptools"

5.使用gpscp实用程序将软件包复制到Greenplum数据库主机。例如,此命令将tar文件从当前主机复制到文件remote-hosts中列出的主机系统。

gpscp -fremote-hosts setuptools-18.4.tar.gz =:/home/gpadmin

6.运行命令以在文件中列出的主机上使用gpssh实用程序构建,安装和测试软件包

远程主机。 filelleGreenplum数据库段主持人:

gpssh -fremote_hosts

>>>tar -xzvf distribute-0.6.21.tar.gz >>> cd setuptools-18.4

>>>python setup.py build && python setup.py install >>> python -c"import setuptools"

>>>exit

setuptools包会安装easy_install实用程序,该实用程序允许您从PythonPackage Index存储库安装Python包。例如,该命令从Python PackageIndex站点安装Python PIP实用程序。

easy_installpip

您可以使用gpssh实用程序在所有Greenplum数据库段主机上运行easy-install命令

 

Complex Python Installation Example (NumPy)

本示例手动安装Python PackageIndex存储库中的Python setuptools模块。

该模块可让您轻松下载,构建,安装,升级和卸载Python软件包。

这个例子首先从一个包中构建模块,然后将模块安装在一个主机上。 然后模块被构建并安装在段主机上。

1.从Python包索引站点获取模块包。 例如,作为gpadmin用户在Greenplum数据库主机上运行此wget命令以获取tar文件。

wget--no-check-certificatehttps://pypi.python.org/packages/source/s/setuptools/setuptools-18.4.tar.gz

 

这个例子构建并安装了Python模块NumPy。 NumPy是Python的科学计算模块。有关NumPy的信息,请参阅http://www.numpy.org/。

构建NumPy包需要这个软件:

•OpenBLAS库,BLAS(基本线性代数子程序)的开源实现。

gcc编译器:gcc,gcc-gfortran和gcc-c ++。编译器需要构建OpenBLAS库。请参阅OpenBLAS先决条件

此示例过程假定yum安装在Greenplum数据库段主机上,并且gpadmin用户是主机上具有root权限的sudoers成员。

下载OpenBLAS和NumPy源文件。例如,这些wget命令将tar文件下载到目录包中:

wget--directory-prefix=packages http://github.com/xianyi/OpenBLAS/tarball/v0.2.8

wget--directory-prefix=packageshttp://sourceforge.net/projects/numpy/files/NumPy/1.8.0/numpy-1.8.0.tar.gz/download

 

将软件分发到Geeenplum数据库主机。例如,如果您将软件下载到

/home/gpadmin/packages这些命令将在主机上创建目录,并将软件复制到gpdb_remotes文件中列出的主机的主机。

gpssh -fgpdb_remotes mkdir packages

gpscp -f gpdb_remotes packages/* =:/home/gpadmin/packages

OpenBLAS Prerequisites

如果需要,请使用yum从系统存储库安装gcc编译器。 所有编译OpenBLAS的主机都需要编译器:

sudo yum -y install gcc gcc-gfortran gcc-c++

注意:如果你不能用yum安装正确的编译器版本,你可以从源代码下载包括gfortran的gcc编译器并安装它们。 这两个命令下载并安装编译器:

wget http://gfortran.eom/download/x86_64/snapshots/gcc-4.4.tar.xz

tar xf gcc-4.4.tar.xz -C /usr/local/

如果您从tar文件手动安装gcc,请将新的gcc二进制文件添加到PATH和LD_LIBRARY_PATH中:

export PATH=$PATH:/usr/local/gcc-4.4/bin

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/gcc-4.4/lib

创建一个符号链接到g ++并称之为gxx

sudo ln -s /usr/bin/g++ /usr/bin/gxx

您可能还需要创建具有不同版本的库的符号链接,例如libppl_c.so.4到libppl_c.so.2。

如果需要,可以使用gpscp实用程序将文件复制到Greenplum数据库主机,然后使用gpssh实用程序在主机上运行命令。

Build and Install OpenBLAS Libraries

Before build and install the NumPymodule, you install the OpenBLAS libraries. This section describes how to buildand install the libraries on a single host.

1.  Extract theOpenBLAS files from the file. These commands extract the files from theOpenBLAS tar file and simplify the directory name that contains the OpenBLASfiles.

tar -xzf packages/vO.2.8 -C /home/gpadmin/packages

mv /home/gpadmin/packages/xianyi-OpenBLAS-9c51cdf/home/gpadmin/packages/OpenBLAS

2.  CompileOpenBLAS. These commands set the library_path environment variable and run the make command to build OpenBLAS libraries.

cd /home/gpadmin/packages/OpenBLAS exportLIBRARY_PATH=$LD_LIBRARY_PATH make FC=gfortran USE_THREAD=0 _

3.  These commandsinstall the OpenBLAS libraries in /usr/local as root and change the owner of thefiles to gpadmin.

cd/home/gpadmin/packages/OpenBLAS/ sudo make PREFIX=/usr/local install sudoldconfig

sudo chown -R gpadmin /usr/local/lib

These are thelibraries that are installed and symbolic links that are created:

libopenblas.a-> libopenblas_sandybridge-r0.2.8.a

libopenblas_sandybridge-r0.2.8.a

libopenblas_sandybridge-r0.2.8.so

libopenblas.so-> libopenblas_sandybridge-r0.2.8.so

libopenblas.so.0-> libopenblas_sandybridge-r0.2.8.so

 

您可以使用gpssh实用程序在多个主机上构建和安装OpenBLAS库。

所有Greenplum数据库主机(主机和网段主机)具有相同的配置。 您可以从构建它们的系统中复制OpenBLAS库,而不是在所有主机上构建OpenBlas库。 例如,这些gpssh和gpscp命令在gpdb_remotes文件中列出的主机上复制并安装OpenBLAS库

 

gpssh-f gpdb_remotes -e 'sudo yum -y install gcc gcc-gfortran gcc-c++'

gpssh-f gpdb_remotes -e 'ln -s /usr/bin/g++ /usr/bin/gxx'

gpssh-f gpdb_remotes -e sudo chown gpadmin /usr/local/lib

gpscp-f gpdb_remotes /usr/local/lib/libopen*sandy* =:/usr/local/lib

gpssh-f gpdb_remotes

>>>cd /usr/local/lib

>>>ln -s libopenblas_sandybridge-r0.2.8.a libopenblas.a

>>>ln -s libopenblas_sandybridge-r0.2.8.so libopenblas.so

>>>ln -s libopenblas_sandybridge-r0.2.8.so libopenblas.so.0

>>>sudo ldconfig

 

Build and Install NumPy

安装OpenBLAS库后,可以构建并安装NumPy模块。 这些步骤将NumPy模块安装在单个主机上。 您可以使用gpssh实用程序来构建和安装NumPy

模块在多个主机上。

1.转到packages子目录,获取NumPy模块源文件并提取文件。

cd /home/gpadmin/packages

tar -xzf numpy-1.8.0.tar.gz

2.建立构建和安装NumPy的环境。

exportBLAS=/usr/local/lib/libopenblas.a

exportLAPACK=/usr/local/lib/libopenblas.a

exportLD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/

exportLIBRARY_PATH=$LD_LIBRARY_PATH

3.转到NumPy目录并构建并安装NumPy。 构建NumPy包可能需要一些时间。

 

cdnumpy-1.8.0

python setup.pybuild

python setup.py install

 

注意:如果NumPy模块没有成功构建,NumPy构建过程可能需要一个指定OpenBLAS库位置的site.cfg。 在NumPy包目录中创建文件site.cfg:

cd 〜/packages/numpy-1.8    

touch site.cfg     

Add the following to the site.cfg file and run the NumPy build commandagain:

 [default]

library_dirs =/usr/local/lib

[atlas]

atlas_libs =openblas

library_dirs =/usr/local/lib

[lapack]

lapack_libs =openblas

library_dirs =/usr/local/lib

# added forscikit-learn

[openblas]

libraries =openblas

library_dirs =/usr/local/lib

include_dirs = /usr/local/include

4.以下Python命令确保模块可以在主机系统上由Python导入。

python -c "import numpy"

与在简单模块安装中一样,您可以使用gpssh实用程序在Greenplum数据库段主机上构建,安装和测试模块。

运行Python NumPy函数时,在gpadmin用户环境中也需要构建NumPy模块所需的环境变量。 您可以使用带有echo命令的gpssh实用程序将环境变量添加到.bashrc文件。 例如,这些echo命令将环境变量添加到用户主目录中的.bashrc文件。

 

echo -e '\n#Needed for NumPy' >>~/.bashrc

echo -e 'exportBLAS=/usr/local/lib/libopenblas.a' >> ~/.bashrc

echo -e 'exportLAPACK=/usr/local/lib/libopenblas.a' >> ~/.bashrc

echo -e 'exportLD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib' >> ~/.bashrc

echo -e 'exportLIBRARY_PATH=$LD_LIBRARY_PATH' >> ~/.bashrc

 

 

Testing Installed Python Modules

您可以创建一个简单的PL/Python用户定义函数(UDF)来验证Greenplum数据库中是否有可用的Python模块。 这个例子测试了NumPy模块。

这个PL/Python UDF导入NumPy模块。 如果模块导入,函数返回SUCCESS;如果导入错误,则返回FAILURE。

 

CREATE OR REPLACE FUNCTIONplpy_test(x int)

returns text

as $$

 try:

    from numpy import *

    return 'SUCCESS'

 except ImportError, e:

    return 'FAILURE'

$$ language plpythonu;

 

创建一个包含每个Greenplum数据库段实例的数据的表。 根据您的Greenplum数据库安装的大小,您可能需要生成更多的数据以确保数据分发到所有的段实例。

CREATE TABLE DIST AS (SELECT x FROMgenerate_series(1,50) x ) DISTRIBUTED RANDOMLY ;

此SELECT命令在数据存储在主段实例中的段主机上运行UDF。

SELECT gp_segment_id, plpy_test(x) AS status

FROM dist

GROUP BY gp_segment_id, status

ORDER BY gp_segment_id, status;

 

如果UDF在Greenplum数据库段实例上导入了Python模块,则SELECT命令返回SUCCESS。如果SELECT命令返回FAILURE,则可以找到段实例主机的段主机。 Greenplum数据库系统表gp_segment_configuration包含有关镜像和段配置的信息。该命令返回段ID的主机名。

 

SELECT hostname, content AS seg_ID FROMgp_segment_configuration WHERE content = seg_id ;

如果FAILURE返回,这是一些可能的原因:

•访问所需库的问题。 对于NumPy示例,Greenplum数据库可能在访问分段主机上的OpenBLAS库或Python库时遇到问题。

确保在gpadmin用户的段主机上运行命令时不会出现错误。 这个gpssh命令测试在段主机mdw1上导入numpy模块。

gpssh -h mdw1 python -c "import numpy"

•如果Python导入命令没有返回错误,则可能不会在Greenplum数据库环境中配置环境变量。 例如,变量不在.bashrc文件中,或者在向环境变量添加环境变量之后可能没有重新启动Greenplum数据库

确保环境变量正确设置,然后重新启动Greenplum数据库。 对于NumPy示例,请确保在主节点和网段主机上的gpadmin用户的.bashrc文件中定义了“构建和安装NumPy”一节末尾列出的环境变量。

注意:在Greenplum数据库主节点和节点主机上,gpadmin用户的.bashrc文件必须获取文件$GPHOME/greenplum_path.sh.


 


示例

This PL/PythonUDF returns the maximum of two integers:

 

CREATEFUNCTION pymax (a integer, b integer)

  RETURNS integer

AS$$

  if (a is None) or (b is None):

    return None

  if a > b:

    return a

  return b

$$LANGUAGE plpythonu;

 

 

您可以使用STRICT属性来执行空处理,而不是使用两个条件语句。

CREATEFUNCTION pymax (a integer, b integer)

  RETURNS integer AS $$

returnmax(a,b)

您可以使用SELECT命令运行用户定义的函数pymax。 这个例子运行UDF并显示输出。

SELECT ( pymax(123, 43));

 column1

123

(1 row)

这个例子从一个针对表运行的SQL查询中返回数据。 这两个命令创建一个简单的表并向表中添加数据。

CREATE TABLE sales (id int,year int, qtr int, day int, region text)

DISTRIBUTED BY (id) ;

INSERT INTO sales VALUES

(1, 2014, 1,1, 'usa'),

(2, 2002, 2,2, 'europe'),

(3, 2014, 3,3, 'asia'),

(4, 2014, 4,4, 'usa'),

(5, 2014, 1,5, 'europe'),

(6, 2014, 2,6, 'asia'),

(7, 2002, 3,7, 'usa') ;

 

这个PL/Python UDF执行一个SELECT命令,从表中返回5行。 Python函数从输入值指定的行中返回REGION值。 在Python函数中,行编号从0开始。函数的有效输入是0到4之间的整数。

CREATE OR REPLACE FUNCTIONmypytest(a integer)

 RETURNS text

AS $$

 rv = plpy.execute("SELECT * FROM sales ORDER BY id", 5)

 region = rv[a]["region"]

 return region

$$ language plpythonu;

 

运行此SELECT语句将返回结果集第三行的REGION列值。

SELECT mypytest(2);

 

This command deletesthe UDF from the database.

DROP FUNCTIONmypytest(integer);


 


References

Technical References

For information about PL/Python seethe PostgreSQL documentation at  http://www.postgresql.org/docs/8.2/static/plpython.html..

For information about Python PackageIndex (PyPI), see https://pypi.python.org/pypi.

These are some Python modules that canbe downloaded:

•    SciPy libraryprovides user-friendly and efficient numerical routines such as routines fornumerical integration and optimization http://www.scipy.org/scipylib/index.html. This wget command downloads the SciPypackage tar file.

wget http://sourceforge.net/projects/scipy/files/scipy/0.10.1/scipy-0.10.1.tar.gz/download

•    NaturalLanguage Toolkit (nltk) is a platform for building Python programs to work withhuman language data. http://www.nltk.org/. This wget command downloads the nltkpackage tar file.

wget http://pypi.python.Org/packages/source/n/nltk/nltk-2.0.2.tar.gz#md5=6e714ff74c3398e88be084748df4e657

Note: The Python package Distribute https://pypi.python.org/pypi/distribute is required for nltk. The Distributemodule should be installed the ntlk package. This wget command downloads theDistribute package tar file.

wget http://pypi.python.org/packages/source/d/distribute/distribute-0.6.21.tar.gz

Useful Reading

For information about the Pythonlanguage, see hftp./www.python.org/.

Aset of slides that were used in a talk about how the Pivotal data science teamuses the PyData stack in the Pivotal MPP databases and on Pivotal Cloud Foundry http://www.slideshare.net/SrivatsanRamanujam/all-thingspythonpivotal.

你可能感兴趣的:(Chapter 15 PL/Python 语言扩展)