查找有关 Apache Phoenix 及其部署的常见问题解答。
是的。Apache Phoenix 用于 OLTP(在线事务处理)用例,而不是 OLAP(在线分析处理)用例。不过,您可以将 Phoenix 用于实时数据摄取作为主要用例。
典型的 Phoenix 部署具有以下内容:
Phoenix 客户端/JDBC 驱动程序本质上是一个 Java 库,您应该将其包含在您的 Java 代码中。Phoenix 使用 HBase 作为存储,类似于 HBase 使用 HDFS 作为存储的方式。但是,Phoenix 的抽象还没有完成,例如为了实现访问控制,您需要在包含 Phoenix 数据的底层 HBase 表上设置 ACL。

对于 Phoenix 应用程序,您必须遵循与 HBase 相同的大小调整指南。有关 Phoenix 性能调优的更多信息,请访问 https://phoenix.apache.org/tuning_guide.html。
是的,您可以使用 Kerberos 进行身份验证。您可以使用 HBase 授权配置授权。
您可以将 HBase 的本机行时间戳映射到 Phoenix 列。通过这样做,您可以利用 HBase 为存储文件的时间范围提供的各种优化以及 Phoenix 内置的各种查询优化功能。
有关更多信息,请参阅https://phoenix.apache.org/rowtimestamp.html
Phoenix 在全局索引维护期间执行本地索引以防止死锁。:当索引更新失败时,Phoenix 还会部分自动重建索引 ( PHOENIX-1112 )。
序列是一个标准的 SQL 特性,它允许生成通常用于形成 ID 的单调递增数字。
有关更多信息,请参阅https://phoenix.apache.org/sequences.html。
写入是持久的,持久性由提交到磁盘(在预写日志中)的 WRITE 定义。因此,在 RegionServer 发生故障的情况下,可以通过重放 WAL 来恢复写入。“完整”写入是已从 WAL 刷新到 HFile 的写入。任何失败都将表示为异常。
是的,您可以在 Phoenix 中进行批量插入。有关更多信息,请参阅https://phoenix.apache.org/bulk_dataload.html。
是的,但不推荐或不支持。数据是由 Phoenix 编码的,因此您必须对数据进行解码才能读取。直接写入 HBase 表会导致 Phoenix 损坏。
是的,只要使用 Phoenix 数据类型。您必须使用异步索引并手动更新它们,因为 Phoenix 不会知道任何更新。
Thick驱动器
jdbc:phoenix:[comma-separated ZooKeeper Quorum [:port [:hbase root znode [:kerberos_principal [:path to kerberos keytab] ] ] ]最简单的网址是:
jdbc:phoenix:localhost
而最复杂的 URL 是:
jdbc:phoenix:zookeeper1.domain,zookeeper2.domain,zookeeper3.domain:2181:/hbase-1:phoenix@EXAMPLE.COM:/etc/security/keytabs/phoenix.keytab请注意,URL 中的每个可选元素都需要之前的所有可选元素。例如,以指定根HBase的Z序节点,动物园管理员端口必须也被指定。
此信息最初包含在索引页上。
Phoenix Thin Driver(与 Phoenix Query Server 一起使用)JDBC URL 语法如下:
jdbc:phoenix:thin:[key=value[;key=value...]]有许多密钥公开供客户端使用。最常用的键是:url和serialization。该网址的关键是需要与Phoenix网查询服务器进行交互。
最简单的网址是:
jdbc:phoenix:thin:url=http://localhost:8765其中非常复杂的 URL 是:
jdbc:phoenix:thin:url=http://queryserver.domain:8765;serialization=PROTOBUF;authentication=SPENGO;principal=phoenix@EXAMPLE.COM;keytab=/etc/security/keytabs/phoenix.keytab有关瘦客户端 JDBC URL 中受支持选项的完整列表,请参阅Apache Avatica 文档,或参阅查询服务器文档
CSV
可以使用名为 psql 的内置实用程序批量加载 CSV 数据。典型的 upsert 速率是每秒 20K - 50K 行(取决于行的宽度)。
用法示例: 使用 psql 创建表$ psql.py [zookeeper] ../examples/web_stat.sql
Upsert CSV 批量数据$ psql.py [zookeeper] ../examples/web_stat.csv
您可以通过 CREATE TABLE/CREATE VIEW DDL 语句在预先存在的 HBase 表上创建 Phoenix 表或视图。在这两种情况下,我们将保留 HBase 元数据原样。对于 CREATE TABLE,我们将创建任何尚不存在的元数据(表、列族)。我们还将为每一行添加一个空键值,以便查询按预期运行(无需在扫描期间投影所有列)。
另一个警告是字节序列化的方式必须与 Phoenix 的字节序列化方式相匹配。对于 VARCHAR、CHAR 和 UNSIGNED_* 类型,我们使用 HBase Bytes 方法。CHAR 类型只需要单字节字符,UNSIGNED 类型需要大于或等于零的值。对于有符号类型(TINYINT、SMALLINT、INTEGER 和 BIGINT),Phoenix 将翻转第一位,以便负值排在正值之前。因为 HBase 按字典顺序对行键进行排序,负值的第一位是 1 而正值是 0,所以如果我们不翻转第一位,负值就会“大于”正值。因此,如果您通过 HBase 本机 API 存储整数并希望通过 Phoenix 访问它们,请确保您的所有数据类型都是 UNSIGNED 类型。
我们的复合行键是通过简单地将值连接在一起形成的,在可变长度类型之后使用一个零字节字符作为分隔符。
如果您像这样创建 HBase 表:
create 't1', {NAME => 'f1', VERSIONS => 5}那么你有一个名为“t1”的 HBase 表和一个名为“f1”的列族。请记住,在 HBase 中,您不会对可能的 KeyValues 或行键的结构进行建模。这是您在 Phoenix 中指定的超出表和列族的信息。
因此,在 Phoenix 中,您将创建一个如下所示的视图:
CREATE VIEW "t1" ( pk VARCHAR PRIMARY KEY, "f1".val VARCHAR )“pk”列声明您的行键是 VARCHAR(即字符串),而“f1”.val 列声明您的 HBase 表将包含具有列族和列限定符“f1”:VAL 的键值,并且它们的值将是一个 VARCHAR。
请注意,如果您使用所有大写名称创建 HBase 表,则不需要双引号(因为这是 Phoenix 通过大写字母对字符串进行规范化的方式)。例如,与:
create 'T1', {NAME => 'F1', VERSIONS => 5}你可以创建这个Phoenix视图:
CREATE VIEW t1 ( pk VARCHAR PRIMARY KEY, f1.val VARCHAR )或者,如果您正在创建新的 HBase 表,只需让 Phoenix 像这样为您做所有事情(根本不需要使用 HBase shell。):
CREATE TABLE t1 ( pk VARCHAR PRIMARY KEY, val VARCHAR )使用Salting提高读/写性能 Salting 可以通过将数据预先拆分到多个区域来显着提高读/写性能。尽管在大多数情况下加盐会产生更好的性能。
例子:
CREATE TABLE TEST (HOST VARCHAR NOT NULL PRIMARY KEY,DESCRIPTION VARCHAR) SALT_BUCKETS=16注意:理想情况下,对于具有四核 CPU 的 16 个区域服务器集群,选择 32-64 之间的盐桶以获得最佳性能。
例子:
CREATE TABLE TEST (HOST VARCHAR NOT NULL PRIMARY KEY,DESCRIPTION VARCHAR) SPLIT ON ('CS','EU','NA')列族在单独的文件中包含相关数据。如果您查询使用选定的列,那么将这些列组合在一个列族中以提高读取性能是有意义的。
例子:
下面的 create table DDL 将创建两个列 faimiles A 和 B。
创建表测试(MYKEY VARCHAR NOT NULL PRIMARY KEY、A.COL1 VARCHAR、A.COL2 VARCHAR、B.COL3 VARCHAR)
例子:
CREATE TABLE TEST (HOST VARCHAR NOT NULL PRIMARY KEY, description VARCHAR) COMPRESSION='GZ'从 Phoenix 2.1 版开始,Phoenix 支持对可变和不可变数据进行索引。请注意,Phoenix 2.0.x 仅支持对不可变数据进行索引。不可变表的索引写入性能指标比可变表稍快,但不可变表中的数据无法更新。
例子
不可变表:
create table test (mykey varchar primary key, col1 varchar, col2 varchar) IMMUTABLE_ROWS=true;可变表:
create table test (mykey varchar primary key, col1 varchar, col2 varchar);在 col2 上创建索引
create index idx on test (col2)create index idx on test (col1) include (col2)Upsert 这个测试表中的行,Phoenix 查询优化器会选择正确的索引来使用。如果 Phoenix 正在使用索引表,您可以在解释计划中看到。您还可以在 Phoenix 查询中提示使用特定索引。
除非查询中使用的所有列都在其中(作为索引或覆盖的列),否则不会使用二级索引。构成数据表主键的所有列都将自动包含在索引中。
示例:
DDL create table usertable (id varchar primary key, firstname varchar, lastname varchar); create index idx_name on usertable (firstname);查询:
DDL select id, firstname, lastname from usertable where firstname = 'foo';在这种情况下不会使用索引,因为姓氏不是索引或覆盖列的一部分。这可以通过查看解释计划来验证。要修复此创建具有索引的姓氏部分或覆盖列的索引。示例:
create idx_name on usertable (firstname) include (lastname);Phoenix很快。100M 行的全表扫描通常在 20 秒内完成(中型集群上的窄表)。如果查询包含键列上的过滤器,这个时间会减少到几毫秒。对于非键列或非前导键列上的过滤器,您可以在这些列上添加索引,通过制作带有索引列的表的副本作为键的一部分,从而获得与对键列进行过滤等效的性能。
为什么即使进行全扫描,Phoenix 也很快:
查看 Anil Gupta 的精彩帖子http://bigdatanoob.blogspot.com/2013/09/connect-phoenix-to-secure-hbase-cluster.html
Hadoop-2 配置文件存在于 Phoenix pom.xml 中。
默认情况下,Phoenix 让 HBase 管理时间戳,并只显示所有内容的最新值。然而,Phoenix 也允许用户提供任意时间戳。为此,您需要在连接时指定“CurrentSCN”,如下所示:
Properties props = new Properties();
props.setProperty("CurrentSCN", Long.toString(ts));
Connection conn = DriverManager.connect(myUrl, props);
conn.createStatement().execute("UPSERT INTO myTable VALUES ('a')");
conn.commit();以上相当于使用 HBase API 执行此操作:
myTable.put(Bytes.toBytes('a'),ts);通过指定 CurrentSCN,您告诉 Phoenix 您希望在该时间戳完成该连接的所有操作。请注意,这也适用于在连接上完成的查询 - 例如,上面 myTable 上的查询不会看到它刚刚插入的数据,因为它只能看到在其 CurrentSCN 属性之前创建的数据。这提供了一种执行快照、闪回或时间点查询的方法。
请记住,创建新连接并不是一项昂贵的操作。相同的底层 HConnection 用于到同一个集群的所有连接,因此它或多或少类似于实例化一些对象。
DDL: CREATE TABLE TEST (pk1 char(1) not null, pk2 char(1) not null, pk3 char(1) not null, non-pk varchar CONSTRAINT PK PRIMARY KEY(pk1, pk2, pk3));RANGE SCAN 意味着只会扫描表中行的一个子集。如果您使用主键约束中的一个或多个前导列,则会发生这种情况。未过滤前导 PK 列的查询,例如。select * from test where pk2='x' and pk3='y'; 将导致完全扫描,而以下查询将导致范围扫描select * from test where pk1='x' and pk2='y'; . 请注意,您可以在“pk2”和“pk3”列上添加二级索引,这将导致对第一个查询(通过索引表)进行范围扫描。
DEGENERATE SCAN 意味着查询不可能返回任何行。如果我们可以在编译时确定这一点,那么我们甚至不必费心运行扫描。
FULL SCAN 意味着将扫描表的所有行(如果您有 WHERE 子句,则可能会应用过滤器)
SKIP SCAN 意味着将扫描表中的一个子集或所有行,但是它会根据过滤器中的条件跳过大组行。有关更多详细信息,请参阅此博客。如果前导主键列没有过滤器,我们不会执行 SKIP SCAN,但您可以使用 / + SKIP_SCAN / 提示强制执行 SKIP SCAN 。在某些情况下,即当您的前导主键列的基数较低时,它会比 FULL SCAN 更有效。
不,没有必要将 Phoenix JDBC 连接池化。
由于底层的 HBase 连接,Phoenix 的 Connection 对象与大多数其他 JDBC Connection 不同。Phoenix Connection 对象被设计为一种创建成本低的薄对象。如果重复使用 Phoenix Connections,则底层 HBase 连接可能不会始终处于前一个用户的健康状态。最好创建新的 Phoenix Connections 以确保避免任何潜在问题。
为 Phoenix 实现池化可以简单地通过创建一个委托 Connection 来完成,该连接在从池中检索时实例化一个新的 Phoenix 连接,然后在将其返回到池中时关闭连接(参见PHOENIX-2388)。
需要空的或虚拟的 KeyValue(列限定符为 _0)以确保给定的列可用于所有行。
您可能知道,数据作为 KeyValues 存储在 HBase 中,这意味着为每个列值存储完整的行键。这也意味着除非存储了至少一列,否则根本不存储行键。
现在考虑具有整数主键的 JDBC 行和几个全为空的列。为了能够存储主键,需要存储一个 KeyValue 以表明该行完全存在。此列由您注意到的空列表示。这允许执行“SELECT * FROM TABLE”并接收所有行的记录,即使是那些非 pk 列为空的记录。
即使某些(或所有)记录只有一列为空,也会出现同样的问题。Phoenix 上的扫描将包括空列,以确保仅包含主键(并且所有非键列都为 null)的行将包含在扫描结果中。
原文链接:http://phoenix.apache.org/faq.html
https://docs.cloudera.com/cdp-private-cloud-base/7.1.6/phoenix-faq/topics/phoenix-faq.html