利用Phoenix 为Hbase来建立二级索引。用的是maven整合的,用起来其实蛮简单的就是坑多了点。
maven:
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-core</artifactId>
<version>4.13.2-cdh5.11.2</version>
</dependency>
properties文件:也比较简单 就是driver和url
driver=org.apache.phoenix.jdbc.PhoenixDriver
url=jdbc:phoenix:hbase的IP地址 可以配置多个
工具类:用来创建连接和关闭连接
package com.yjh.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class PhoniexConnectUtils {
private static String driver;
private static String url;
/**
* 静态代码块加载配置文件信息
*/
static {
try {
// 1.通过当前类获取类加载器
ClassLoader classLoader = PhoniexConnectUtils.class.getClassLoader();
// 2.通过类加载器的方法获得一个输入流
InputStream is = classLoader.getResourceAsStream("phoenix.properties");
// 3.创建一个properties对象
Properties props = new Properties();
// 4.加载输入流
props.load(is);
// 5.获取相关参数的值
driver = props.getProperty("driver");
url = props.getProperty("url");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取连接方法
*
* @return
*/
public static Connection getConnection() {
Connection conn = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(url);
} catch (Exception e) {
e.printStackTrace();
System.err.println("连接获取失败");
}
return conn;
}
/**
* 释放资源方法
*
* @param conn
* @param pstmt
* @param rs
*/
public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 释放资源方法
*
* @param conn
* @param pstmt
*/
public static void close(Connection conn, PreparedStatement pstmt) {
if (pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
建表:
package com.yjh.demo1;
import com.yjh.utils.PhoniexConnectUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class CreateTable {
public static void main(String[] args) throws SQLException {
Connection connection = PhoniexConnectUtils.getConnection();
String sql = "CREATE TABLE IF NOT EXISTS \"yjp\".\"orderTest\" (\n" +
" orderIDPK BIGINT NOT NULL,\n" +
" itemIDPK BIGINT NOT NULL,\n" +
" orderID BIGINT,\n" +
" itemID BIGINT,\n" +
" amount DECIMAL\n" +
" CONSTRAINT my_pk PRIMARY KEY (orderIDPK,itemIDPK)) DEFAULT_COLUMN_FAMILY=o ," +
" COLUMN_ENCODED_BYTES=0";
PreparedStatement statement = connection.prepareStatement(sql);
statement.execute();
PhoniexConnectUtils.close(connection, statement);
System.err.println("创建成功");
}
}
第一个坑:\"yjp\".\"orderTest\" Phoenix 底层有自己的解析器,如果没有用双引号约束,那么Phoenix的解析器会默认全大写。
DEFAULT_COLUMN_FAMILY=o 设置默认的列族,如果不自己主动设置,Phoenix默认的列族是0
COLUMN_ENCODED_BYTES 告诉解析器以二进制的方式存放数据
save 保存数据
package com.yjh.demo1;
import com.yjh.utils.PhoniexConnectUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class SaveData {
public static void main(String[] args) throws SQLException {
Connection connection = PhoniexConnectUtils.getConnection();
connection.setAutoCommit(true);
PreparedStatement preparedStatement = null;
String sql = "UPSERT INTO \"yjp\".\"orderTest\" VALUES(1,2,1,2,12.3)";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.execute();
PhoniexConnectUtils.close(connection, preparedStatement);
System.err.println("保存成功");
}
}
如果在创建表的时候用了\"yjp\".\"orderTest\"那么在保存数据指定表的时候必须一致,不然会因为解析器的原因找不到表。
第二个坑,A在这张表上面建立了a这个列族,然后A去往Hbase中删除了这张表。B此时又建立了这张表,重新给了列族o,我们此时去save的时候就会发现,默认的列族是a,这是因为我们在建立a这个列族的还是不仅仅是建立在这张表中,同时也建立到系统表中,系统表会有记录。所以在需要删除表的时候最好用程序删除。
删除表:
package com.yjh.demo1;
import com.yjh.utils.PhoniexConnectUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class DeleteTable {
public static void main(String[] args) throws SQLException {
Connection connection = PhoniexConnectUtils.getConnection();
String sql = "Drop table \"yjp\".\"orderTest\"";
PreparedStatement statement = connection.prepareStatement(sql);
statement.execute();
PhoniexConnectUtils.close(connection, statement);
System.err.println("删除成功");
}
}
这里的删除是drop 不是delete
查询表:
package com.yjh.demo1;
import com.yjh.utils.PhoniexConnectUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class SelectTable {
public static void main(String[] args) throws SQLException {
Connection connection = PhoniexConnectUtils.getConnection();
String sql = "select * from \"yjp\".\"orderTest\" where OrderIDPK = ?";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setObject(1,1);
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
System.err.println(resultSet.getObject("amount"));
}
PhoniexConnectUtils.close(connection, statement, resultSet);
System.err.println("查询成功");
}
}
查询和我们用jdbc差不多的。
建立索引:
package com.yjh.demo1;
import com.yjh.utils.PhoniexConnectUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class CreateIndex {
public static void main(String[] args) throws SQLException {
Connection connection = PhoniexConnectUtils.getConnection();
String sql = "CREATE Index \"my_test_index\" on \"yjp\".\"orderTest\"(orderID)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.execute();
PhoniexConnectUtils.close(connection, statement);
System.err.println("创建索引成功");
}
}
需要指明建立索引的字段。
删除索引:
package com.yjh.demo1;
import com.yjh.utils.PhoniexConnectUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class DeleteIndex {
public static void main(String[] args) throws SQLException {
Connection connection = PhoniexConnectUtils.getConnection();
String sql = "DROP Index \"my_test_index\" on \"yjp\".\"orderTest\"";
PreparedStatement statement = connection.prepareStatement(sql);
statement.execute();
PhoniexConnectUtils.close(connection, statement);
System.err.println("删除索引成功");
}
}
删除指定名称的索引。
在使用Phoenix 的时候Hbase中的列族最好只有一个,方便查询。然后在经常需要查询的列上建立索引。建立索引的时候最好建立 String sql = "CREATE LOCAL Index \"wb_index\" on \"yjp\".\"WbOrder\"(orderID)"; 通过测试建立本地索引查询时间相差10倍。
努力吧,皮卡丘。