Indexes

自 3.0 起删除索引

还有一些替代选项可能与索引相似:

Note

索引已在 3.0 版(HIVE-18448)中被“删除”。

Introduction

本文解释了为 Hive(HIVE-417)添加索引支持的建议设计。索引是一种标准的数据库技术,但是有许多可能的变化。我们采用的方法不是尝试提供“一刀切”的索引实现,而是采用可插拔的方式定义索引(与StorageHandlers相关),并提供一个具体的索引实现作为参考,从而为随着时间的流逝,贡献者可以插入其他索引方案。直到 Hive 0.7 才提供索引支持。

Scope

仅支持单表索引。一旦 Hive 支持了其他视图(例如联接索引),则可以更恰当地将其表示为实例化视图。

本文档当前仅涵盖索引的创建和维护。后续文章将说明如何使用索引优化查询(构建在FilterPushdownDev上)。

CREATE INDEX

CREATE INDEX index_name
ON TABLE base_table_name (col_name, ...)
AS 'index.handler.class.name'
[WITH DEFERRED REBUILD]
[IDXPROPERTIES (property_name=property_value, ...)]
[IN TABLE index_table_name]
[PARTITIONED BY (col_name, ...)]
[
   [ ROW FORMAT ...] STORED AS ...
   | STORED BY ...
]
[LOCATION hdfs_path]
[TBLPROPERTIES (...)]
[COMMENT "index comment"]

有关 ROW FORMAT 等各种子句的详细信息,请参见Create Table

默认情况下,索引分区与基表的分区匹配。 PARTITIONED BY 子句可用于指定表分区列的子集(此列列表可能为空,以指示索引跨越表的所有分区)。例如,即使索引仅按日期进行分区(每个索引分区跨越所有区域),也可以按日期区域对表进行分区。

无法在视图上创建索引。我们(最终)将在非本机表上支持它们(如果相应的存储处理程序指示它支持它们)。

索引处理程序可能要求被索引的基表具有特定格式。

问题:我们应该允许 EXTERNAL 表上的索引吗?删除表后,这对于隐式 DROP 意味着什么?是否存在 EXTERNAL 索引的概念?

如果索引处理程序以表格形式存储其表示形式,则可以使用 index_table_name 来控制为此目的自动创建的“索引表”的名称。可以使用 STORED AS(例如 RCFILE 或 SEQUENCFILE)或 STORED BY(例如将索引表存储在 nonlocal 表(例如 HBase)中)来控制索引表的存储格式,尽管某些索引处理程序可能需要使用特定的存储格式。并非所有的索引处理程序都以表格形式存储它们的表示形式。一些可能使用非表文件,而另一些可能使用完全在 Hive 外部维护的结构(例如,持久键/值存储)。

Metastore Model

下图显示了具有索引支持的新 Metastore 模式:

http://issues.apache.org/jira/secure/attachment/12449601/idx2.png

Metastore 模式中的新 IDXS 表每个创建的索引包含一个条目。它与 TBLS 表有两个关系:

因此,给定以下 DDL:

CREATE TABLE t(i int, j int);
CREATE INDEX x ON TABLE t(j)
AS 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler';

元存储中的 TBLS 表将具有两个条目:

在 x 的 IDXS 条目中,ORIG_TBL_ID 将引用 x 的 TBL_ID,IDX_TBL_ID 将引用default+t_x+的 TBL_ID。

为了避免生成名称,可以改为提供用户指定的名称,例如 t_x:

CREATE INDEX x ON TABLE t(j)
AS 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'
IN TABLE t_x;

请注意,索引名称由包含的基表(如分区)限定,因此可以在两个不同的表中使用相同的索引名称。但是,索引表的名称与所有其他表和视图在同一命名空间中,因此它们在同一数据库中必须唯一。

索引具有一个存储 Descriptors,该 Descriptors 包含索引所覆盖的原始表中的列的子集。如果索引表示形式存储在表中,则索引自身的存储 Descriptors 中的其他大多数字段(例如 LOCATION)将是无关紧要的。

TBD:

Metastore Upgrades

这是 MySQL Metastore 升级声明。

DROP TABLE IF EXISTS {{IDXS}};
CREATE TABLE {{IDXS}} (
  {{INDEX_ID}} bigint(20) NOT NULL,
  {{CREATE_TIME}} int(11) NOT NULL,
  {{DEFERRED_REBUILD}} bit(1) NOT NULL,
  {{INDEX_HANDLER_CLASS}} varchar(256) DEFAULT NULL,
  {{INDEX_NAME}} varchar(128) DEFAULT NULL,
  {{INDEX_TBL_ID}} bigint(20) DEFAULT NULL,
  {{LAST_ACCESS_TIME}} int(11) NOT NULL,
  {{ORIG_TBL_ID}} bigint(20) DEFAULT NULL,
  {{SD_ID}} bigint(20) DEFAULT NULL,
  PRIMARY KEY ({{INDEX_ID}}),
  UNIQUE KEY {{UNIQUEINDEX}} ({{INDEX_NAME}},{{ORIG_TBL_ID}}),
  KEY {{IDXS_FK1}} ({{SD_ID}}),
  KEY {{IDXS_FK2}} ({{INDEX_TBL_ID}}),
  KEY {{IDXS_FK3}} ({{ORIG_TBL_ID}}),
  CONSTRAINT {{IDXS_FK3}} FOREIGN KEY ({{ORIG_TBL_ID}}) REFERENCES {{TBLS}} ({{TBL_ID}}),
  CONSTRAINT {{IDXS_FK1}} FOREIGN KEY ({{SD_ID}}) REFERENCES {{SDS}} ({{SD_ID}}),
  CONSTRAINT {{IDXS_FK2}} FOREIGN KEY ({{INDEX_TBL_ID}}) REFERENCES {{TBLS}} ({{TBL_ID}})
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Table structure for table {{INDEX_PARAMS}}
--

DROP TABLE IF EXISTS {{INDEX_PARAMS}};
CREATE TABLE {{INDEX_PARAMS}} (
  {{INDEX_ID}} bigint(20) NOT NULL,
  {{PARAM_KEY}} varchar(256) NOT NULL,
  {{PARAM_VALUE}} varchar(767) DEFAULT NULL,
  PRIMARY KEY ({{INDEX_ID}},{{PARAM_KEY}}),
  CONSTRAINT {{INDEX_PARAMS_FK1}} FOREIGN KEY ({{INDEX_ID}}) REFERENCES {{IDXS}} ({{INDEX_ID}})
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

REBUILD

ALTER INDEX index_name ON table_name [PARTITION (...)] REBUILD

有关 PARTITION 子句的语法,请参见LanguageManual DDL#Add_Partitions

如果在 CREATE INDEX 上指定了 WITH DEFERRED REBUILD,则新创建的索引最初为空(无论表是否包含任何数据)。 ALTER INDEX ... REBUILD 命令可用于为所有分区或单个分区构建索引结构。

如果基表中的数据发生更改,则必须使用 REBUILD 命令使索引更新。这是一个原子操作,因此如果该表先前已被索引,并且重建失败,则旧索引保持不变。

DROP INDEX

DROP INDEX index_name ON table_name

可以使用 DROP INDEX 随时删除索引。这也将级联到索引表(如果存在)。

尝试直接使用 DROP TABLE 删除索引表将失败。

当删除索引基表时,DROP 隐式级联到所有索引(及其对应的索引表,如果有的话)。

当索引基表删除其分区之一时,这将隐式级联以从所有索引中删除相应的分区。

问题:如果索引分区粒度与表分区粒度不同,该怎么办?可能只是忽略删除操作,而让用户使用新的 ALTER INDEX DROP PARTITION 语句进行手动清理。

Plugin Interface

索引处理程序具有以下主要职责:

下面定义了相应的 Java 接口以及处理程序应扩展的伴随抽象 Base Class。

package org.apache.hadoop.hive.ql.metadata;

import java.util.List;

import org.apache.hadoop.conf.Configurable;

import org.apache.hadoop.hive.ql.plan.api.Task;

/**
 * HiveIndexHandler defines a pluggable interface for adding new
 * index handlers to Hive.
 */
public interface HiveIndexHandler extends Configurable
{
  /**
 * Determines whether this handler implements indexes by creating
 * an index table.
   *
 * @return true if index creation implies creation of an index table in Hive;
 * false if the index representation is not stored in a Hive table
   */
  boolean usesIndexTable();

  /**
 * Requests that the handler validate an index definition and
 * fill in additional information about its stored representation.
 *
 * @param baseTable the definition of the table being indexed
   *
 * @param index the definition of the index being created
   *
 * @param indexTable a partial definition of the index table to be used for
 * storing the index representation, or null if usesIndexTable() returns
 * false; the handler can augment the index's storage descriptor
 * (e.g. with information about input/output format)
 * and/or the index table's definition (typically with additional
 * columns containing the index representation, e.g. pointers into HDFS)
   *
 * @throw HiveException if the index definition is invalid with
 * respect to either the base table or the supplied index table definition
   */
  void analyzeIndexDefinition(
    org.apache.hadoop.hive.metastore.api.Table baseTable,
    org.apache.hadoop.hive.metastore.api.Index index,
    org.apache.hadoop.hive.metastore.api.Table indexTable)
      throws HiveException;

  /**
 * Requests that the handler generate a plan for building the index;
 * the plan should read the base table and write out the index representation.
   *
 * @param baseTable the definition of the table being indexed
   *
 * @param index the definition of the index
   *
 * @param partitions a list of specific partitions of the base
 * table for which the index should be built, or null if
 * an index for the entire table should be rebuilt
   *
 * @param indexTable the definition of the index table, or
 * null if usesIndexTable() returns null
   *
 * @return list of tasks to be executed in parallel for building
 * the index
   *
 * @throw HiveException if plan generation fails
   */
  List<Task<?>> generateIndexBuildTaskList(
    org.apache.hadoop.hive.metastore.api.Table baseTable,
    org.apache.hadoop.hive.metastore.api.Index index,
    List<org.apache.hadoop.hive.metastore.api.Partition> partitions,
    org.apache.hadoop.hive.metastore.api.Table indexTable)
      throws HiveException;
}

/**
 * Abstract base class for index handlers.  This is provided as insulation
 * so that as HiveIndexHandler evolves, default implementations of new
 * methods can be added here in order to avoid breaking existing
 * plugin implementations.
 */
public abstract class AbstractIndexHandler implements HiveIndexHandler
{
}

对于 CREATE INDEX,Hive 首先在处理程序上调用 usingIndexTable()以确定是否将创建索引表。如果返回 false,则如果用户为索引指定了任何表存储选项,则该语句将立即失败。但是,如果 usesIndexTable()返回 true,则 Hive 会根据索引定义(例如覆盖的列)以及用户提供的任何表存储选项,为索引表创建部分表定义。接下来,Hive 调用 analyticsIndexDefinition(为 indexTable 参数传递 null 或部分索引表定义)。处理程序通过验证定义进行响应(如果检测到任何不受支持的组合,则引发异常),然后将有关 index 和 indexTable 参数的附加信息填充为输出。然后,Hive 将这些结果存储在 metastore 中。

TBD:我们将添加删除索引时调用处理程序的方法(例如,为将索引表示形式存储在外部系统(例如 HBase)中的处理程序提供清理机会)

Reference Implementation

参考实现将创建所谓的“紧凑”索引。这意味着,它不存储每次出现特定值的 HDFS 位置,而是仅存储包含该值的 HDFS 块的地址。在值通常在附近的行中多次出现的情况下,此方法针对点查找进行了优化。索引大小保持较小,因为块少于行。权衡是在查询过程中需要额外的工作才能从索引块中滤除其他行。

紧凑索引存储在索引表中。索引表列由基础表中的索引列组成,其后是_bucketname 字符串列(指示包含已索引块的文件的名称),其后是_offsets array<string>列(指示相应文件中的块偏移)。索引表按排序方式存储在索引列上(但不存储在生成的列上)。

参考实现可以插入

ADD JAR /path/to/hive_idx-compact.jar;
CREATE INDEX ...
AS 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler';

TBD:用于构建索引的算法

TBD:搜索索引的机制

TBD:在基表上验证(可以是任何托管表吗?)

TBD:验证索引表格式(可以是任何托管表格式吗?)

TBD

当前状态(JIRA)

||
||
|T|Key|Summary|Assignee|Reporter|P|Status|Resolution|Created|Updated|Due|

Loading...

Refresh

首页