这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

Java SDK

Vertica SDK 支持编写除聚合函数之外的所有类型的 Java UDx。所有 Java UDx 均被隔离。

您可以下载、编译和运行示例;请参阅下载并运行 UDx 示例代码。运行示例是验证您的开发环境是否具有所有需要的库的好方法。

如果您无权访问 Vertica 测试环境,则可以在开发计算机上安装 Vertica 并运行单个节点。每次重建 UDx 库时,都需要将其重新安装到 Vertica。下图说明了典型开发周期。

此部分涵盖适用于所有 UDx 类型的特定于 Java 的主题。有关适用于所有语言的信息,请参阅实参和返回值UDx 参数错误、警告和日志记录处理取消请求和特定 UDx 类型的章节。如需完整的 API 文档,请参阅 Java SDK 文档。

1 - 设置 Java SDK

Vertica Java 软件开发工具包 (SDK) 将作为服务器安装的一部分分发。它包含创建 UDx 库所需的源文件和 JAR 文件。有关可以编译和运行的示例,请参阅下载并运行 UDx 示例代码

要求

至少需要在开发计算机上安装下列资源:

  • 与您已在数据库主机上安装的 Java 版本相匹配的 Java 开发工具包 (JDK) 版本(请参阅在 Vertica 主机上安装 Java)。

  • Vertica SDK 的副本。

或者,您可以使用内部版本管理工具(例如 make)来简化开发。

SDK 文件

要使用 SDK,您需要 Java 支持包中的两个文件:

  • /opt/vertica/bin/VerticaSDK.jar 包含 Vertica Java SDK 和其他支持文件。

  • /opt/vertica/sdk/BuildInfo.java 包含有关 SDK 的版本信息。您必须编译此文件并将其包含到 Java UDx JAR 文件中。

如果您不在数据库节点上进行开发,则可以从数据库节点之一将这两个文件复制到开发系统。

用来编译 UDx 的 BuildInfo.javaVerticaSDK.jar 文件必须来自同一个 SDK 版本。这两个文件还必须与 Vertica 主机上的 SDK 文件的版本匹配。只有不在 Vertica 主机上编译 UDx 时,版本控制才会出现问题。如果要在单独的开发系统上进行编译,请始终刷新这两个文件的副本,并在部署之前重新编译 UDx。

开发 UDx 时,计划使用的 SDK 版本必须与其所在的数据库版本相同。要显示当前安装在系统上的 SDK 版本,请在 vsql 中运行以下命令:

=> SELECT sdk_version();

编译 BuildInfo.java

您需要将 BuildInfo.java 文件编译到类文件中,以便可以将该文件包含到 Java UDx JAR 库中。如果要使用 Vertica 节点作为开发系统,您可以执行以下任一操作:

  • BuildInfo.java 文件复制到主机上的其他位置。

  • 如果您没有 root 权限,请在原位置编译 BuildInfo.java 文件。(只有 root 用户拥有将文件写入到 /opt/vertica/sdk 目录的权限。)

使用以下命令编译文件。将 path 替换为文件的路径,并将 output-directory 替换为将在其中编译 UDx 的目录。

$ javac -classpath /opt/vertica/bin/VerticaSDK.jar \
      /path/BuildInfo.java -d output-directory

如果使用诸如 Eclipse 等 IDE,则您可以将 BuildInfo.java 文件包含到项目中,而不必单独编译此文件。您还必须将 VerticaSDK.jar 文件添加到项目的构建路径中。有关如何将文件和库包含到项目中的详细信息,请参阅 IDE 的文档。

运行示例

您可以从 GitHub 存储库下载示例(请参阅下载并运行 UDx 示例代码)。编译和运行示例有助于确保正确设置开发环境。

如果您尚未这样做,请将 JAVA_HOME 环境变量设置为您的 JDK(而非 JRE)目录。

要编译所有示例(包括 Java 示例),请在示例目录下的 Java-and-C++ 目录中执行以下命令:

$ make

要仅编译 Java 示例,请在示例目录下的 Java-and-C++ 目录中执行以下命令:

$ make JavaFunctions

2 - 编译并打包 Java 库

您需要先编译 Java UDx 并将其打包到 JAR 文件中,然后才能开始使用。

SDK 示例包括一个工作生成文件。请参阅下载并运行 UDx 示例代码

编译 Java UDx

编译 Java UDx 源文件时,您需要将 SDK JAR 文件包含到 CLASSPATH 中,以便 Java 编译器可以解析 Vertica API 调用。如果要使用位于数据库群集中的主机上的命令行 Java 编译器,请输入以下命令:

$ javac -classpath /opt/vertica/bin/VerticaSDK.jar factorySource.java \
      [functionSource.java...] -d output-directory

如果所有源文件均位于同一个目录中,则您可以在命令行中使用 *.java,而不必逐个列出文件。

如果要使用 IDE,请验证 VerticaSDK.jar 文件的副本是否位于构建路径中。

UDx 类文件组织

编译 UDx 之后,您必须将其类文件和 BuildInfo.class 文件打包到 JAR 文件中。

要使用打包在 JDK 中的 jar 命令,您必须将 UDx 类文件组织成与类包结构匹配的目录结构。例如,假设 UDx 的工厂类的完全限定名称为 com.mycompany.udfs.Add2ints。在这种情况下,类文件必须位于目录层次结构 com/mycompany/udfs(相对于项目的基本目录)中。此外,您还必须将 BuildInfo.class 文件的副本放到路径 com/vertica/sdk 中,以便可以将该副本包含到 JAR 文件中。此类必须存在于 JAR 文件中,以指示用于编译 Java UDx 的 SDK 版本。

Add2ints UDSF 示例的 JAR 文件在编译后具有以下目录结构:

com/vertica/sdk/BuildInfo.class
com/mycompany/example/Add2intsFactory.class
com/mycompany/example/Add2intsFactory$Add2ints.class

将 UDx 打包到 JAR 文件中

要从命令行创建 JAR 文件,请执行下列操作:

  1. 更改为项目的根目录。

  2. 使用 jar 命令打包 BuildInfo.class 文件和 UDx 中的所有类:

    # jar -cvf libname.jar com/vertica/sdk/BuildInfo.class \
           packagePath/*.class
    

    键入此命令时,libname 表示为 JAR 文件选择的文件名(您可以随意选择任何名称),packagePath 表示包含 UDx 的类文件的目录的路径。

    • 例如,要打包 Add2ints 示例中的文件,请使用以下命令:

      # jar -cvf Add2intsLib.jar com/vertica/sdk/BuildInfo.class \
      com/mycompany/example/*.class
      
    • 更简单来说,如果已将 BuildInfo.class 和类文件打包到同一个根目录中,则您可以使用以下命令:

      # jar -cvf Add2intsLib.jar .
      

    您必须将构成 UDx 的所有类文件包含到 JAR 文件中。UDx 始终包含至少两个类(工厂类和函数类)。即使您已将函数类定义为工厂类的内部类,Java 也会为内部类生成单独的类文件。

将 UDx 打包到 JAR 文件之后,您便已准备好将其部署到 Vertica 数据库。

3 - 处理 Java UDx 依赖项

如果 Java UDx 依赖一个或多个外部库,您可以通过以下三种方法之一处理依赖项:

  • 使用工具(例如,One-JAR 或 Eclipse Runnable JAR Export Wizard)将 JAR 文件捆绑到 UDx JAR 文件中。

  • 将 JAR 文件解包,然后将其内容重新打包到 UDx 的 JAR 文件中。

  • 将库复制到 Vertica 群集和 UDx 库。然后使用 CREATE LIBRARY 语句的 DEPENDS 关键字向 Vertica 说明 UDx 库依赖外部库。此关键字用作特定于库的 CLASSPATH 设置。Vertica 会将支持库分发给群集中的所有节点,并设置 UDx 的类路径以便能够找到这些支持库。

    如果 UDx 依赖本地库(SO 文件),请使用 DEPENDS 关键字指定其路径。调用 UDx 中的 System.loadLibrary(使用本地库之前必须执行此操作)时,此函数使用 DEPENDS 路径来查找这些库。您不需要另外设置 LD_LIBRARY_PATH 环境变量。

外部库示例

以下示例演示了将外部库与 Java UDx 结合使用。

以下示例代码定义了一个名为 VowelRemover 的简单类。此类包含名为 removevowels 的单个方法,该方法将从字符串中移除所有元音字母(字母 aeiouy)。

package com.mycompany.libs;

public class VowelRemover {
    public String removevowels(String input) {
        return input.replaceAll("(?i)[aeiouy]", "");
    }
};

可以使用以下命令编译此类并将其打包到 JAR 文件中:

$ javac -g com/mycompany/libs/VowelRemover.java
$ jar cf mycompanylibs.jar com/mycompany/libs/VowelRemover.class

以下代码定义了一个名为 DeleteVowels Java UDSF,它使用在以上示例代码中定义的库。 DeleteVowels 接受单个 VARCHAR 作为输入,并返回 VARCHAR。

package com.mycompany.udx;
// Import the support class created earlier
import com.mycompany.libs.VowelRemover;
// Import the Vertica SDK
import com.vertica.sdk.*;

public class DeleteVowelsFactory extends ScalarFunctionFactory {

    @Override
    public ScalarFunction createScalarFunction(ServerInterface arg0) {
        return new DeleteVowels();
    }

    @Override
    public void getPrototype(ServerInterface arg0, ColumnTypes argTypes,
            ColumnTypes returnTypes) {
        // Accept a single string and return a single string.
        argTypes.addVarchar();
        returnTypes.addVarchar();
    }

    @Override
    public void getReturnType(ServerInterface srvInterface,
            SizedColumnTypes argTypes,
            SizedColumnTypes returnType){
        returnType.addVarchar(
        // Output will be no larger than the input.
        argTypes.getColumnType(0).getStringLength(), "RemovedVowels");
    }

    public class DeleteVowels extends ScalarFunction
    {
        @Override
        public void processBlock(ServerInterface arg0, BlockReader argReader,
                BlockWriter resWriter) throws UdfException, DestroyInvocation {

            // Create an instance of the  VowelRemover object defined in
            // the library.
            VowelRemover remover = new VowelRemover();

            do {
                String instr = argReader.getString(0);
                // Call the removevowels method defined in the library.
                resWriter.setString(remover.removevowels(instr));
                resWriter.next();
            } while (argReader.next());
        }
    }

}

可以使用以下命令构建示例 UDSF 并将其打包到 JAR 中:

  • 第一个 javac 命令可编译 SDK 的 BuildInfo 类。Vertica 要求所有 UDx 库包含此类。此 javac 命令的 -d 选项可在 UDSF 源的目录结构中输出类文件。

  • 第二个 javac 命令可编译 UDSF 类。此命令可将先前创建的 mycompanylibs.jar 文件添加到类路径,以便编译器能够找到 VowelRemover 类。

  • jar 命令可将 BuildInfo 和 UDx 库的类打包到一起。

$ javac -g -cp /opt/vertica/bin/VerticaSDK.jar\
   /opt/vertica/sdk/com/vertica/sdk/BuildInfo.java -d .
$ javac -g -cp mycompanylibs.jar:/opt/vertica/bin/VerticaSDK.jar\
  com/mycompany/udx/DeleteVowelsFactory.java
$ jar cf DeleteVowelsLib.jar com/mycompany/udx/*.class \
   com/vertica/sdk/*.class

要安装 UDx 库,您必须将两个 JAR 文件同时复制到 Vertica 群集中的节点。然后连接到该节点以执行 CREATE LIBRARY 语句。

以下示例演示了如何在复制 JAR 文件之后将 UDx 库加载到 dbadmin 用户的主目录。DEPENDS 关键字可向 Vertica 说明 UDx 库依赖 mycompanylibs.jar 文件。

=> CREATE LIBRARY DeleteVowelsLib AS
   '/home/dbadmin/DeleteVowelsLib.jar' DEPENDS '/home/dbadmin/mycompanylibs.jar'
   LANGUAGE 'JAVA';
CREATE LIBRARY
=> CREATE FUNCTION deleteVowels AS language 'java' NAME
  'com.mycompany.udx.DeleteVowelsFactory' LIBRARY DeleteVowelsLib;
CREATE FUNCTION
=> SELECT deleteVowels('I hate vowels!');
 deleteVowels
--------------
  ht vwls!
(1 row)

4 - Java 和 Vertica 数据类型

Vertica Java SDK 将Vertica 的原生数据类型转换为相应的 Java 数据类型。下表列出了 Vertica 数据类型及其相应的 Java 数据类型。

设置 BINARY、VARBINARY 和 LONG VARBINARY 值

Vertica BINARY、VARBINARY 和 LONG VARBINARY 数据类型将转换为 Java UDx SDK 的 VString 类。您还可以通过 PartitionWriter.setStringBytes() 方法使用 ByteBuffer 对象(或包装在 ByteBuffer 中的字节数组)来设置具有这些数据类型的列的值。有关详细信息,请参阅 PartitionWriter.setStringBytes() 的 Java API UDx 条目。

时间戳和时区

当 SDK 将 Vertica 时间戳转换为 Java 时间戳时,它使用 JVM 的时区。如果 JVM 运行的时区与 Vertica 使用的时区不同,则结果可能会令人困惑。

Vertica 以 UTC 格式将时间戳存储在数据库中。(如果设置了数据库时区,则在查询时完成转换。)为了防止来自 JVM 时区的错误,请将以下代码添加到 UDx 的处理方法中:

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

字符串

Java SDK 包含一个名为 StringUtils 的类,此类可帮助处理字符串数据。getStringBytes() 方法是此类的较有用的功能之一。此方法可以从 String 提取字节并防止创建无效字符串。如果尝试提取会将多字节 UTF-8 字符拆分为多个部分的子字符串,getStringBytes() 会将该子字符串截断为最近似的完整字符。

5 - 处理 NULL 值

UDx 必须准备好处理 NULL 值。这些值通常必须与正则值分开进行处理。

读取 NULL 值

UDx 将从 BlockReader 类或 PartitionReader 类的实例读取数据。如果列的值为 NULL,则用来获取数据的方法(例如 getLong)将返回 Java null 引用。如果您在未检查 NULL 的情况下尝试使用该值,Java 运行时将抛出空指针异常。

您可以在读取列之前使用特定于数据类型的方法(例如,isLongNullisDoubleNullisBooleanNull)测试 null 值。例如,要测试 UDx 输入的第一列的 INTEGER 数据类型是否为 NULL,请使用以下语句:

// See if the Long value in column 0 is a NULL
if (inputReader.isLongNull(0)) {
    // value is null
    . . .

写入 NULL 值

可以使用特定于类型的方法(例如 setLongNullsetStringNull)在 BlockWriter 类和 PartitionWriter 类上输出 NULL 值。这些方法使用列号来接收 NULL 值。此外,PartitionWriter 类具有特定于数据类型的设置值方法(例如 setLongValuesetStringValue)。如果向这些方法传递某个值,这些方法会将输出列设置为该值。如果向这些方法传递 Java null 引用,这些方法会将输出列设置为 NULL。

6 - 将元数据添加到 Java UDx 库

您可以将诸如作者姓名、库版本以及库描述之类的元数据添加到您的库。此元数据可以让您跟踪在 Vertica 分析数据库群集上部署的函数的版本并让您函数的第三方用户了解该函数的创建者。库加载到 Vertica 分析数据库编录之后,库的元数据会出现在 USER_LIBRARIES 系统表中。

要向 Java UDx 库添加元数据,请创建 UDXLibrary 类(包括库的元数据)的子类。然后,您可以将该类包含到 JAR 文件中。使用 CREATE LIBRARY 语句将类加载到 Vertica 分析数据库编录时,请查找 UDXLibrary 的子类以获取库的元数据。

UDXLibrary 的子类中,您需要实施八个 getter,它们将返回包含库的元数据的字符串值。此类中的 getter 如下:

  • getAuthor() 将返回您要用来与创建的库关联的名称(例如,您自己的名字或您的公司的名称)。

  • getLibraryBuildTag() 将返回您要用来表示库的特定内部版本的任何字符串(例如,SVN 修订号或编译该库时的时间戳)。开发库实例时,跟踪这些库实例很有用。

  • getLibraryVersion() 将返回库的版本。您可以使用想使用的任何编号或命名方案。

  • getLibrarySDKVersion() 将返回您为其编译了库的 Vertica 分析数据库 SDK 库的版本。

  • getSourceUrl() 将返回一个 URL,函数用户可以通过此 URL 找到有关该函数的详细信息。这可以是您公司的网站、托管库源代码的 GitHub 页面或您喜欢的任何站点。

  • getDescription() 将返回库的简要描述。

  • getLicensesRequired() 将返回用于许可信息的占位符。您必须为此值传递一个空字符串。

  • getSignature() 将返回用于签名(此签名将对库进行身份验证)的占位符。您必须为此值传递一个空字符串。

例如,以下代码演示了创建 UDXLibrary 子类并将其包含到 Add2Ints UDSF 示例 JAR 文件中(请参阅任何 Vertica 代码上的 /opt/vertica/sdk/examples/JavaUDx/ScalarFunctions)。

// Import the UDXLibrary class to hold the metadata
import com.vertica.sdk.UDXLibrary;

public class Add2IntsLibrary extends UDXLibrary
{
    // Return values for the metadata about this library.

    @Override public String getAuthor() {return "Whizzo Analytics Ltd.";}
    @Override public String getLibraryBuildTag() {return "1234";}
    @Override public String getLibraryVersion() {return "1.0";}
    @Override public String getLibrarySDKVersion() {return "7.0.0";}
    @Override public String getSourceUrl() {
        return "http://example.com/add2ints";
    }
    @Override public String getDescription() {
        return "My Awesome Add 2 Ints Library";
    }
    @Override public String getLicensesRequired() {return "";}
    @Override public String getSignature() {return "";}
}

当加载包含 Add2IntsLibrary 类的库时,元数据将显示在 USER_LIBRARIES 表中:

=> CREATE LIBRARY JavaAdd2IntsLib AS :libfile LANGUAGE 'JAVA';
CREATE LIBRARY
=> CREATE FUNCTION JavaAdd2Ints as LANGUAGE 'JAVA'  name 'com.mycompany.example.Add2IntsFactory' library JavaAdd2IntsLib;
CREATE FUNCTION
=> \x
Expanded display is on.
=> SELECT * FROM USER_LIBRARIES WHERE lib_name = 'JavaAdd2IntsLib';
-[ RECORD 1 ]-----+---------------------------------------------
schema_name       | public
lib_name          | JavaAdd2IntsLib
lib_oid           | 45035996273869844
author            | Whizzo Analytics Ltd.
owner_id          | 45035996273704962
lib_file_name     | public_JavaAdd2IntsLib_45035996273869844.jar
md5_sum           | f3bfc76791daee95e4e2c0f8a8d2737f
sdk_version       | v7.0.0-20131105
revision          | 125200
lib_build_tag     | 1234
lib_version       | 1.0
lib_sdk_version   | 7.0.0
source_url        | http://example.com/add2ints
description       | My Awesome Add 2 Ints Library
licenses_required |
signature         |

7 - Java UDx 资源管理

当启动时,Java 虚拟机 (JVM) 会分配固定数量的内存。此固定内存分配机制会使 Java UDx 的内存管理复杂化,因为 UDx 在处理数据时无法动态分配和释放内存。与此不同的是,C++ UDx 可以动态分配资源。

为了控制 Java UDx 所占用的内存量,Vertica 包含一个名为 jvm 的内存池,它使用该池为 JVM 分配内存。如果该内存池已用完,则在该池中有足够内存可用于启动新的 JVM 之前,调用 Java UDx 的查询会阻塞。

默认情况下,jvm 池存在以下情况:

  • 由于没有分配给自己的内存,它会从 GENERAL 池借用内存。

  • 其 MAXMEMORYSIZE 设置为系统内存的 10% 或 2 GB(以较小者为准)。

  • 其 PLANNEDCONCURRENCY 设置为 AUTO,因此它会继承 GENERAL 池的 PLANNEDCONCURRENCY 设置。

您可以通过查询 RESOURCE_POOLS 表来查看 jvm 池的当前设置:

=> SELECT MAXMEMORYSIZE,PLANNEDCONCURRENCY FROM V_CATALOG.RESOURCE_POOLS WHERE NAME = 'jvm';
 MAXMEMORYSIZE | PLANNEDCONCURRENCY
---------------+--------------------
 10%           | AUTO

当 SQL 语句调用 Java UDx 时,Vertica 会检查 jvm 内存池是否具有足够内存可用于启动新的 JVM 实例以执行函数调用。在启动每个新的 JVM 时,Vertica 会将其堆内存大小设置为大约 jvm 池的 MAXMEMORYSIZE 参数除以其 PLANNEDCONCURRENCY 参数。如果内存池不包含足够内存,则在另一个 JVM 退出并将其内存返回到池中之前,查询会阻塞。

如果 Java UDx 尝试使用的内存多于已分配给 JVM 堆大小的内存,它会退出并显示错误。您可以尝试通过以下方法解决此问题:

  • 增加 jvm 池的 MAXMEMORYSIZE 参数。

  • 减少 jvm 池的 PLANNEDCONCURRENCY 参数。

  • 更改 Java UDx 的代码以使用更少内存。

调整 jvm 池

根据需求调整 jvm 池,您必须考虑以下两个因素:

  • Java UDx 运行所需的 RAM 容量

  • 您希望数据库运行多少个并发 Java UDx 函数

您可以使用几种方法来了解 Java UDx 所需的内存数量。例如,您的代码可以使用 Java 的 Runtime 类来获取已分配的总内存的估算值并使用 ServerInterface.log() 记录该值。(此类的一个实例将传递给您的 UDx。)如果数据库中有多个 Java UDx,请基于使用最多内存的 UDx 设置 jvm 池的内存大小。

需要运行 Java UDx 的并发会话数不能与全局 PLANNEDCONCURRENCY 设置相同。例如,您可能只有一个用户运行 Java UDx,这意味着您可以将 jvm 池的 PLANNEDCONCURRENCY 设置减少至 1。

在获取 RAM 数量的估算值和需要运行 Java UDX 的并发用户会话数之后,您可以将 jvm 池调整为适当大小。将该池的 MAXMEMORYSIZE 设置为需要最多资源的 Java UDx 所需的最大 RAM 容量乘以运行 Java UDx 所需的并发用户会话数。将该池的 PLANNEDCONCURENCY 设置为运行 Java Udx 所需的并发用户会话数。

例如,假设您的 Java UDx 最多需要 4 GB 内存才能运行,并且您希望最多有两个用户会话使用 Java UDx。您应使用以下命令调整 jvm 池:

=> ALTER RESOURCE POOL jvm MAXMEMORYSIZE '8G' PLANNEDCONCURRENCY 2;

MEMORYSIZE 已设置为 8 GB,即 Java UDx 使用的最大内存 (4 GB) 乘以并发用户会话数(2 个)。

有关对 jvm 和其他资源池进行优化的详细信息,请参阅管理工作负载

释放 JVM 内存

当用户在其会话期间第一次调用 Java UDx 时,Vertica 会分配 jvm 池中的内存并启动新的 JVM。只要用户会话处于打开状态,此 JVM 就会保持运行,以便可以处理其他 Java UDx 调用。让 JVM 保持运行可以减少由同一个会话执行多个 Java Udx 所产生的开销。如果 JVM 不保持处于打开状态,则对 Java UDx 的每次调用都会导致 Vertica 需要耗费更多时间来分配资源和启动新的 JVM。但是,让 JVM 保持处于打开状态意味着无论是否会再次使用 JVM 的内存,该内存在会话的有效期内都会保持处于已分配状态。

如果减小 jvm 内存池,则包含 Java UDx 的查询会在内存变为可用之前阻塞,或者最终会由于缺少资源而失败。如果发现查询由于此原因而阻塞或失败,您可以向 jvm 池分配更多内存并增加其 PLANNEDCONCURRENCY。另一个选项是要求用户在他们不再需要运行 Java UDx 时调用 RELEASE_JVM_MEMORY 函数。此函数可关闭属于该用户会话的任何 JVM 并将其已分配的内存恢复到 jvm 内存池中。

以下示例演示了查询 V_MONITOR.SESSIONS 以确定所有会话已分配给 JVM 内存。此示例还演示了如何通过调用 Java UDx 来分配内存以及如何通过调用 RELEASE_JVM_MEMORY 来释放内存。

=> SELECT USER_NAME,EXTERNAL_MEMORY_KB FROM V_MONITOR.SESSIONS;
 user_name | external_memory_kb
-----------+---------------
 dbadmin   |             0
(1 row)

=> -- Call a Java UDx
=> SELECT add2ints(123,456);
 add2ints
----------
      579
(1 row)
=> -- JVM is now running and memory is allocated to it.
=> SELECT USER_NAME,EXTERNAL_MEMORY_KB FROM V_MONITOR.SESSIONS;
 USER_NAME | EXTERNAL_MEMORY_KB
-----------+---------------
 dbadmin   |         79705
(1 row)

=> -- Shut down the JVM and deallocate memory
=> SELECT RELEASE_JVM_MEMORY();
           RELEASE_JVM_MEMORY
-----------------------------------------
 Java process killed and memory released
(1 row)

=> SELECT USER_NAME,EXTERNAL_MEMORY_KB FROM V_MONITOR.SESSIONS;
 USER_NAME | EXTERNAL_MEMORY_KB
-----------+---------------
 dbadmin   |             0
(1 row)

在极少数情况下,您可能需要关闭所有 JVM。例如,您可能需要为重要查询释放内存,或者 Java UDx 的多个实例可能需要太长时间才能完成。您可以使用 RELEASE_ALL_JVM_MEMORY 关闭所有用户会话中的所有 JVM:

=> SELECT USER_NAME,EXTERNAL_MEMORY_KB FROM V_MONITOR.SESSIONS;
  USER_NAME  | EXTERNAL_MEMORY_KB
-------------+---------------
 ExampleUser |         79705
 dbadmin     |         79705
(2 rows)

=> SELECT RELEASE_ALL_JVM_MEMORY();
                           RELEASE_ALL_JVM_MEMORY
-----------------------------------------------------------------------------
 Close all JVM sessions command sent. Check v_monitor.sessions for progress.
(1 row)

=> SELECT USER_NAME,EXTERNAL_MEMORY_KB FROM V_MONITOR.SESSIONS;
 USER_NAME | EXTERNAL_MEMORY_KB
-----------+---------------
 dbadmin   |             0
(1 row)

注意

  • jvm 资源池仅用于为语句中的 Java UDx 函数分配内存。SQL 语句所需的其余资源来自其他内存池。

  • 第一次调用 Java UDx 时,Vertica 会启动 JVM 以执行某些 Java 方法,从而在查询规划阶段获取有关 UDx 的元数据。此 JVM 的内存也是从 jvm 内存池获取的。