Drill: Hive 插件

Drill 1.1 及后续的版本支持Hive 1.0;要使用Hive的自定义SerDes或是输入格式、输出格式来访问Hive 的表,所有的Drill节点必须在Drill安装目录的jars/3rdparty 目录下放上Hive的SerDes或是输入格式,输出格式的Jar包。

你可以通过选择WEB办控制台里的”Storage” tab来更新Hive配置。从禁用的手件列表里, 点击”hive”后面的”Update”按钮。Hive默认的插件的配置应当像下面这样:

{
      "type": "hive",
      "enabled": false,
      "configProps": {
        "hive.metastore.uris": "",
        "javax.jdo.option.ConnectionURL": "jdbc:derby:;databaseName=../sample-data/drill_hive_db;create=true",
        "hive.metastore.warehouse.dir": "/tmp/drill_hive_wh",
        "fs.default.name": "file:///",
        "hive.metastore.sasl.enabled": "false"
      }
    }

Drill连接到Hive的远程元数据

Hive的元数据是在Hive之外做为一个独立服务存的的。Drill可以能冠军Thrift来访问元数据。元数据和Hive数据库是通过JDBC来交互的。

按照这一章后面的步骤来将Drill指向到Hive的元数据服务的地址。在Hive 插件的配置中,设定Connection参数,来给Drill提供一个connection。在这里,如果你并不是通过HBaseStorageHandler来查询Hive 表的,你就已经完成配置了;如果你通过HBaseStorageHandler来查询Hive表,你需要配置Zookeeper quorum 和port这两个属性,因为HBaseStorageHandler需要这两个参数。Drill也使用这些参数来发现HBase 服务。如果你使用HBase 插件,请在Hive插插和HBase 插件里使用相同的Zookeeper quorum 和port 参数(如果你想要Hive 查询访问和HBase一样的源的话)。

注意,请确认你在注册Hive的元数据的时候,Hive元数据服务已经跑起来了。

Hive 远程元数据配置

要连接Drill到一个Hive 远程元数据:

  1. 在hive.metastore.uris配置项里指定的系统上执行这个命令:

hive --service metastore

  1. 在Drill的Web控制台上,点选 “Storage” 标签页。

Drill:HBase 插件

HBase 插件

当使用HBase 插件连接Drill到一个HBase数据源时,你需要指定Zookeeper。Drill支持HBase 版本0.98。

要查看或修改HBase的插件配置,请使用Drill的WEB控制台。在Web控制台,选择Storage tab,点击hbase插件后面的”update”按钮。下面的例子演示了如何定制HBase插件:

 {
          "type": "hbase",
          "config": {
            "hbase.zookeeper.quorum": "10.10.100.62,10.10.10.52,10.10.10.53",
            "hbase.zookeeper.property.clientPort": "2181"
          },
          "size.calculator.enabled": false,
          "enabled": true
        }

Drill:文件系统插件

你可以配置一个存储插件,来让Drill连接到一个本地文件系统,或是在Hadoop的core-site.xml里注册过的分布式文件系统,像是S3或是HDFS。默认情况下,Drill都提供了一个叫dfs的插件配置,指向了您的本地文件系统。

连接Drill到一个文件系统

在一个Drill集群中,您一般不会查询一个本地文件系统,而是将文件放在分布式文件系统中。当前阶段,您连接到多个Drill终端时,为了得到一致的,完整的查询结果,通常都需要一个分布式的文件系统 ,这个可能是通过将文件拷贝到所有的节点来模拟,或是使用NFS,也或者是使用Amazon的弹性云系统。

您 要在插件的工作空间中配置connection 属性,这样Drill才能连接到分布式文件系统;例如,下面的配置可以让Drill从一个客户端连接到HDFS集群:

"connection": "hdfs://<IP Address>:<Port>/"

在集群中,要从一台机器查询HDFS上的文件,你只需要简单地将dfs插件中的connection属性中的”file:///”改成”hdfs://”就行了。

要修改dfs插件的配置来指向不同的本地或分布式文件系统,像下面这样使用connection属性就好了

  • 本地文件系统的例子:
{
    "type": "file",
    "enabled": true,
    "connection": "file:///",
    "workspaces": {
      "root": {
        "location": "/user/max/donuts",
        "writable": false,
        "defaultInputFormat": null
       }
    },
    "formats" : {
      "json" : {
        "type" : "json"
      }
    }
  }

分布式文件系统的例子:

{
    "type" : "file",
    "enabled" : true,
    "connection" : "hdfs://10.10.30.156:8020/",
    "workspaces" : {
      "root" : {
        "location" : "/user/root/drill",
        "writable" : true,
        "defaultInputFormat" : null
      }
    },
    "formats" : {
      "json" : {
        "type" : "json"
      }
    }
  }

要连接到Hadoop的文件系统,你要将name node的IP和端口写在配置中。

甜甜圈例子

下面的例子展示了一个file类型的插件,还带有一个叫json_files的工作空间。这个配置将Drill指向到了本机的/users/max/drill/json/目录(dfs)。

{
  "type" : "file",
  "enabled" : true,
  "connection" : "file:///",
  "workspaces" : {
    "json_files" : {
      "location" : "/users/max/drill/json/",
      "writable" : false,
      "defaultInputFormat" : json
   } 
},

配置里的”connection”选项是”file:///”,将Drill连接到了本地的文件系统 。

要查询示例的json_files工作空间里的文件,你可以使用USE指令来告诉Drill使用json_files工作空间,这个工作空间是指定在dfs插件里的。

USE dfs.json_files;
SELECT * FROM `donuts.json` WHERE type='frosted'

如果json_files 工作空间不存在,查询就需要像下面这样指定完整的路径:

SELECT * FROM dfs.`/users/max/drill/json/donuts.json` WHERE type='frosted';

Drill:关系数据库查询

Apache Drill支持查询某些RDBMS实例。这使得您能将您的传统数据库连接到你的Drill集群中来,您将能够用一个系统中用同一个视图来处理关系数据库和NO-SQL 数据库。

不管是哪一种源,Drill都支持在系统内和多个系统之间进行Join。这包括在一些关系数据库上进行对像join,where,group 这样的语句的推演。

使用关系数据库插件

Drill设计生来就可以和提供了JDBC 驱动的关系数据库一起工作。Drill在Postgres,MySQL,Oracle, MSSQL和Apache Derby 上进行了活跃的测试。针对每一个系统,你都只需要三个基础的步骤来进行启动:

  • 安装Drill,如果您还没有安装的话;
  • 把该数据库的JDBC驱动拷贝到jars/3rdparty 目录下(每个节点都需要这么做)
  • 通过WEB UI给Drill添加新插件的配置。Oracle,SQL Server,Mysql和Postgres的例子马上给出。

示例:和MySQL 一起工作

Drill使用您从WEB UI或是REST API设定的插件配置,通过JDBC 驱动来和MySQL 通信。

在您配置插件之前,请确保Mysql 的服务已经启来了,并且jar文件已经拷贝在指定目录了。

### 配置JDBC插件的方法:

  • 启动Drill ;
  • 打开Drill WEB控制台;
  • 在Storage Tab页,在”New Storage Plugin”区域键入一个名字,例如:myplugin。Drill里面注册的每一个插件都需要一个唯一的名字,名字是大小写敏感的。
  • 点击“Create”。
  • 在配置区域,像下面这样,用JSON格式来设置属性。请做必要的修改,以匹配你自己的实际环境。
{
  "type": "jdbc",
  "driver": "com.mysql.jdbc.Driver",
  "url": "jdbc:mysql://localhost:3306",
  "username": "root",
  "password": "mypassword",
  "enabled": true
}  

  • 点击”Create”。

你可以使用performance_schema数据库来访问随着Mysql安装的performance_schema数据库。请在Where子句里,用小圆点连接插件配置,数据库,表名这种语法;就像下面给出来的一样:

0: jdbc:drill:zk=local> select * from myplugin.performance_schema.accounts;
  +--------+------------+----------------------+--------------------+
  |  USER  |    HOST    | CURRENT_CONNECTIONS  | TOTAL_CONNECTIONS  |
  +--------+------------+----------------------+--------------------+
  | null   | null       | 18                   | 20                 |
  | jdoe   | localhost  | 0                    | 813                |
  | root   | localhost  | 3                    | 5                  |
  +--------+------------+----------------------+--------------------+
  3 rows selected (0.171 seconds)

Oracle 配置示例

下载并将ojdbc7.12.1.0.2.jar 安装到您 的每个Drill节点上:

{
  type: "jdbc",
  enabled: true,
  driver: "oracle.jdbc.OracleDriver",
  url:"jdbc:oracle:thin:user/password@1.2.3.4:1521/ORCL"
}

SQL Server的示例配置

对于SQL Server,Drill已经测试过微软的 sqljdbc41.4.2.6420.100.jar 驱动。将这个文件拷贝到所有的Drill节点上。

您需要在JDBC的连接字符串中提供数据库的名字,以帮助Drill识别MSSQL 协议。

{
  type: "jdbc",
  enabled: true,
  driver: "com.microsoft.sqlserver.jdbc.SQLServerDriver",
  url:"jdbc:sqlserver://1.2.3.4:1433;databaseName=mydatabase",
  username:"user",
  password:"password"
}

MySQL 的配置示例

对于MySQL,Drill已经在 mysql-connector-java-5.1.37-bin.jar 这个驱动上测试过。把它拷贝到所有的Drill节点上。

{
  type: "jdbc",
  enabled: true,
  driver: "com.mysql.jdbc.Driver",
  url:"jdbc:mysql://1.2.3.4",
  username:"user",
  password:"password"
}

Postgres 配置示例

对于Postgres,Drill测试过 9.1-901-1.jdbc4 驱动(近期的版本应该都可以);拷贝这个jar到所有的Drill节点上。

{
  type: "jdbc",
  enabled: true,
  driver: "org.postgresql.Driver",
  url:"jdbc:postgresql://1.2.3.4/mydatabase",
  username:"user",
  password:"password"
}

Drill:工作空间

工作空间

你可以在存储插件的配置项里,配置多个工作空间。工作空间定义了本地或是分布式文件系统里的子目录下的文件。当你查询时,Drill会在所有的工作空间里搜寻以便加载到数据。一个隐式声明的默认的工作空间,“dfs.default”,指向了本地的根文件系统。

下面这个”dfs”的插件的配置展示了定义工作空间的例子:


{ "type": "file", "enabled": true, "connection": "file:///", "workspaces": { "root": { "location": "/", "writable": false, "defaultInputFormat": null }, "tmp": { "location": "/tmp", "writable": true, "defaultInputFormat": null }, "emp": { "location": "/Users/user1/emp", "writable": true, "defaultInputFormat": null }, "donuts": { "location": "/Users/user1/donuts", "writable": true, "defaultInputFormat": null }, "sales": { "location": "/Users/user1/sales", "writable": true, "defaultInputFormat": null } },

将子目录定义为工作空间,可以使查询简化,这对于重复查询同一个文件相当有用。当你在工作空间的location域配置了一个个长长的路径名,在查询的时候,你不需要输入这个长长的路径名,只需要输工作空间名和小圆点就行了:

<workspace name>.`<location>`

\<location>是子目录的名字。

如果你查询的数据源,是你并没有设置成默认schema的插件的,需要把插件的名字带上。(这里假设你没有使用USE plugin.workspace 语句来连接到指定的存储插件):

<plugin>.<workspace name>.`<location>`

覆盖 dsf.default 选项

在有些场景下,比如用户没有读根目录的权限的情况下,你需要覆盖掉dfs.default这个隐藏选项。你需要把下面这么一个叫default的workspace 添加到dfs插件的配置里。

"default": {
  "location": "</directory/path>",
  "writable": true,
  "defaultInputFormat": null
}

无工作空间的Hive 和HBase

你是无法在Apache Drill安装的HBase和Hive 插件选项里配置工作空间的,虽然它们看起来也是按工作空间工作的。每个Hive插件的配置都包含了一个叫default的工作空间,这个工作空间指向了hive的元数据。当你查询Hive的default 工作空间时,你可以在查询语句里忽略工作空间的名字:

SELECT * FROM hive.customers LIMIT 10;
SELECT * FROM hive.`default`.customers LIMIT 10;

提示: Default 是一个关键词,关键词用作表名,字段名等标识符时,需要用反引号括起来。

因为HBase插件完全不适用工作空间,你可以简单地使用这样的查询:

SELECT * FROM hbase.customers LIMIT 10;

Drill:插件的基本配置

当你在一个有多个drill节点的集群中添加或是更新配置的时候,drill会把这个配置变更信息广播到其他的节点,以保持配置的同步。添加,修改配置的时候,并不需要重启任何drillbit节点。

使用Drill的WEB控制台

你可以通过Drill web控制台来修改,添加插件配置。要启动Web console,你需要将Drill shell跑起来。

要创建一个新配置,您需要:

  1. 启动Drill shell[此处应有传送门]
  2. 启动Drill WEB 控制台。[此处应有传送门]
  3. 进到插件tab,输入一个新插件的名字,每个名字都是一个新的存储插件。每个插件的配置都需要有一个全局唯一的名字,名字是区分大小写的。

  1. 点击”create”
  2. 在配置界面,尽可能地从已经有的配置中拷贝再修改JSON配置,这样可以降低json语法错误的风险,在做一些定制修改时,请参照下一章节的存储插件属性表。
  3. 点击”Create”。(译注:原文是”create”,但我认为是笔误,应当是“Update”)。

存储插件的属性配置

下图解释了一个典型的dfs的存储插件的各个key的含义。

属性和概念清单

| 属性 | 示例 | 是否必须 | 说明 |
|—|—|—|—|—| 
| “type” | “file” “hbase” “hive” “mongo” | yes | 必须是一种合法的存储插件的名字 |
| “enabled” | true false | yes | 插件的状态 |
| “connection” | “classpath:///” “file:///” “mongodb://localhost:27017/” “hdfs://” | 依赖于各种具体的实现 | 分布式文件系统的类型,比如HDFS,Amazon S3,或是你本地的文件系统,以及路径名 |
| ”workspace” | null “logs” | no | 一个或多个唯一的命名空间的名字。如果一个名字被使用了多次,只有最后一次是有效的 |
| “workspaces”…”location” | “location”:”/Users/john/mydata/” “location”:”/tmp/” | no | 文件系统上的一个完整路径 |
| “workspaces”…”writable” | true false | no | 如果定义了多次,只有最后一次有效 |
| “workspaces”…”defaultInputFormat” | null “parquet” “csv” json” | no ” 读文件的格式,不考虑扩展名。默认是“Parquet” |
| “formats” | “csv” “psv” “tsv” “parquet” “json” “avro” “maprdb” “sequencefile” | yes | 读取时合法的文件格式。Drill会检测一些文件的格式,其他的需要配置。maprdb的支持是在mapr-drill安装包里提供的 |
| ”formats”…”type” | “text”,”parquet”,”json”,”maprdb”,”avro”,”sequencefile” | yes | 文件格式的类型。你可以把两种格式的,csv ,psv 都定义成“text”类型,但是是不同的分隔符。|
| formats… extensions | [“csv”] | format-dependent | drill能够读取的文件名扩展。|
| formats… delimiter | “\t” “,” | format-dependent | 一个或多个字符的序列,用以在文本文件(例如csv)中做记录的分隔。对于不可见的字符,可以用4位的十六进制(\xXXXX)来指代。|
| formats…quote | “”” | no | 文本文件中,开始或结束一个值用的一个字符 |
| formats…escape | “`” | no | a single character that escapes a quotation mark inside a value |
| formats … comment | “#” | no | 在文本文件中开启一个注释行 |
| formats skipFirstLine | true | no | 在读取文本文件时,包含还是忽略文件头。设置成true,可以避免把文件头当成数据读入 |
| formats extractHeader | true | no | 设置成true,可以把文件头读进来做为列名。在extractHeader=false时,请确保skipFirstLine没有设置成true。 |

使用格式相关属性

你要在存储插件的配置的formats区域设置格式相关的属性,比如skipFirstLine。当设置了text类型的属性时,你需要把sys.options中的exec.storage.enable_new_text_reader 设置成 true ;更多信息,请参照“Text files:CSV,TSV,PSV”章节。

在表参数中使用格式相关属性

从Drill 1.4起,你可以在每一个query中设置格式相关的属性了。To pass parameters to the format plugin ,use the table function syntax:

    select a,b from table({table function name }(parameters));

例如:

    select a, b from table(dfs.`path/to/data.csv`(type => 'text',
fieldDelimiter => ',', extractHeader => true))

大小敏感

在前面提到过,工作空间和存储插件的名字,都是大小写敏感的。
【后面废话太多了 我懒得翻译了。。。】

存储插件的REST API

如果你需要添加一份存储插件的配置,同时又不想使用WEB 浏览器,你可以使用Drill REST API来完成。使用POST方式来请求,并传递 两个属性进来:

  • name 存储插件的名字
  • config 在Web界面里要设置的那个配置

比如,下面这个命令就创建了一个叫myplugin的插件,这个插件读取根文件系统上一个未知类型的文件。

curl -X POST -H "Content-Type: application/json" -d '{"name":"myplugin", "config": {"type": "file", "enabled": false, "connection": "file:///", "workspaces": { "root": { "location": "/", "writable": false, "defaultInputFormat": null}}, "formats": null}}' http://localhost:8047/storage/myplugin.json

这里我们假设https未被启用。

存储插件的启动引导

在分布式的环境下,要通过程序自动化的方式添加存储插件,最推荐的方式是走REST API。另外还有一种方式 ,就是初始化引导方式 ,具体来说,就是在启动drill的时候,创建一个 bootstrap-storage-plugins.json 文件,放在classpath下。当Drill启动的时候,这个文件就会被加载。

当前用引导方式来添加存储插件的配置时,只有集群中的第一个Drillbit在第一次启动的时候才会生效。这个配置存储在ZooKeeper里,因此就再也不会去读那个 bootstrap-storage-plugins.json 文件了。

当集群起来以后,你就只能通过WEB控制台,或是REST API来添加存储插件的配置了。当然你也可以通过直接把那个插件的json文件上传到zookeeper的安装目录下的/drill路径下来修改Zookeeper里的节点,或者,如果不需要再维护相应的属性,直接删除/drill目录就好了。

如果你通过bootstrap-storage-plugins.json文件加载了一个Hbase 的配置,但是HBase并没有安装,在执行查询的时候可能会觉察到一个延时。你可以在HBase的Config 区块内设置HBase 的客户端超时和重试相关的设定。

Drill:存储插件的注册

我们可以通过存储插件连接到本地文件系统,Hive,HBase,或是其他的数据源。在Drill的web界面的存储插件配置tab,你可以查看修改这些插件的配置。如果不支持HTTPS(默认就没有),你可以访问HTTP://{IP}:8047/storage 来查看和配置存储插件。可以用IP,也可以用hostname。如果开启了https的支持,你可以通过https://{IP}:8047/storage来访问。

Drill 默认开启了cp,dfs,hbase,hive和mongodb的插件支持。

  1. cp 指向Drill Classpath里的jar包文件,例如你可以查询employee.json文件。
  2. DFS 指向本地文件系统,你也可以修改这个插件指向任何分布式文件系统,比如hadoop或是amazon的S3文件系统。
  3. hbase 提供到HBase的连接 。
  4. Hive 为Drill提供了访问Hive文件的元数据抽象的集成,也提供了一些库来访问SerDe和UDF.
  5. mongo 提供到mongodb的访问。

在Drill沙箱里,dfs插件为你提供了连接到一个预先定义好的hadoop环境的能力。如果你自己在本地跑一下drill,那么dfs是访问你本地文件系统的根目录。

注册一个存储插件的配置

你只需要输入插件名字,点击”CREATE”,提供一个json格式的配置,再点击”UPDATE”,就可以注册一个新的插件配置。。

## 存储插件的配置的持久化

在嵌入式执行的时候,Drill将配置保存在一个临时目录, 在分布式模式下运行时,drill将配置放在zookeeper中。例如,在Mac OSX下,Drill将配置保存在/tmp/drill/sys.storage_plugins文件中。当你重启电脑的时候,这个临时目录会被清空。当你将drill运行在嵌入模式下时,你可以将sys.store.provider.local.path 配置项添加到drill-override.conf文件里,就像下面这样:

 drill.exec: {
    cluster-id: "drillbits1",
    zk.connect: "localhost:2181",
    sys.store.provider.local.path="/mypath"
 }

Drill:连接到数据源

连接到数据源

存储插件是Drill中,连接到数据源的模块。一个存储插件通常会优化Drill查询的执行,提供数据的定位,命名空间下的配置和读数据要用到的格式。Drill已经内置了一些存储插件,你只需要根据你的环境配置一下就可以使用了。借助存储插件,你可以连接到各种数据源,像数据库,本地或是分布式的文件,或是Hive数据库。

你可以修改一个存储插件的默认配置X,并给一个新的唯一的名字”Y”。这个新的文档就会把Y当成一个完全不同的插件,虽然它本身只是原有插件重新配置了一下。当你执行一个drill查询的时候,Drill通过以下几种方式得到存储插件的配置:

  1. Query中的FROM语句指定要使用的插件。
  2. 在执行Query之前执行USE命令;
  3. 你还可以启动Drill的时候指令存储插件。

存储插件的内部

下图描述了位于Drill和数据源中间的存储插件层:

存储插件层

除了前面进到的这些功能,存储插件层还提供了扫描,写数据的功能,并能够将来自navive层的一些能力,比如动作推断,jon,SQL 等等知会到执行引擎。

Drill:概要

性能

Drill是从地基开始就奔向高性能和大数据集去设计的,下面列出来的是Drill能够做到高性能的核心要点。

分布式的引擎

Drill提供了一个强大的分布式引擎来处理查询。用户可以从集群的任何一个节点是提交查询。你可以添加新的节点到集群中,以为了支持更多用户的更多数据,或是获得更好的性能。

列式执行

通过使用一种纯内存的分层的,列式的数据模型,Drill同时为列式存储,列式执行都做了优化。当数据是存储在列式存储的文件上时(比如像Parquet)Drill会避免去访问那些查询中根本不涉及到的列。Drill的执行层同样可以直接对列式数据进行SQL查询,而不需要做一个分行化的操作。列式存储和直接列式执行,这两个优化的组件显示地降低了内存消耗,并为BI和分析类型的作业提供了更快的执行效率。

向量化

相比一次只处理一个表记录中的一个值 ,Drill中的向量化允许CPU在向量上操作,也就是一批记录上操作。一个记录批次包含来自不同的记录上的一组数值 。向量处理能够做到非常高效的技术基础,在于现在的芯片技术,这些芯片都携带了深度流水线化的CPU设计。让所有管理都达到接近峰值的高效是不可能的,因为代码复杂度太高了。

运行时编译

运行时编译相比解释执行提供了更快的执行。Drill为每一条查询指令都生成了非常高效的指令。下图展示了Drill的编译和指令生成过程。

https://drill.apache.org/docs/img/58.png

乐观并且流水线的查询执行

Drill 使用乐观的执行模型来处理查询,假定在小片的查询中失败是不太常见的。Drill不会浪费时间在创建边界或是检查点上,这样就可以最小化恢复时间。在单条查询失败的时候,这条查询就直接返回了。Drill执行使用一种所有任务一次性安排的流水线模型。查询尽可能地在内存中执行以便能在流水线中完成作业,只有内存不足时才会持久化到磁盘。

Drill:查询的执行

drill 查询的执行

当您提交Drill查询的时候,客户端或应用程序会把查询以SQL语句的形式发送到Drill集群的一个Drillbit。Drillbit是在每个在线的Drill节点上运行的进程,它负责协调,规划和执行查询,并按照最大限度地实现数据本地化的原则在集群中分发查询。

下图描述了客户端,应用和drillbit之前的通信:

https://drill.apache.org/docs/img/query-flow-client.png

从客户端或应用端接收查询的那个drillbit会成为这个查询是的“接待员”,会负责驱动整个查询。这个”接待员“drillbit进程中有一个解析器,这个解析器解析这个SQL语句,应用一系列定制的规则,并把特定的SQL操作符翻译成相应的Drill能理解的逻辑操作符。这一系列逻辑操作符形成了一个逻辑计划。这个逻辑计划描述了为了得到查询结果需要做的工作,以及需要的数据源以及要进行的处理。

这个“接待员”drillbit 会将这个逻辑计划发送到一个基于开销核算的优化器,这个优化器会调整SQL操作符的顺序。优化器会应用各种各样的规则来做操作符和函数的对齐操作,并形成一个物理计划。最终就是,优化器将逻辑计划转换成了一个描述这个查询如何工作的物理计划。

https://drill.apache.org/docs/img/client-phys-plan.png

一个“parallelizer”会将一条物理计划转换成若干条短语,这些短语我们称之为”一级碎片“和”次级碎片“。

https://drill.apache.org/docs/img/execution-tree.PNG

Major Fragments

一个”Major Fragments“是这样一个概念,可以说是代表了Dril查询的一个阶段。一个”阶段(phase)“是Drill执行查询时必须执行的一个或多个操作单元。Drill会给每个Major Fragments 分配一个MajorFragmentID.

例如,为了计算两个文件的Hash,Drill可能就会创建两个主要阶段(两个Major fragments),第一阶段用来扫描文件 ,第二阶段则用来聚合数据。

Major fragments

Drill使用”Exchange Operator “来连接不同的Major fragments。一个”exchange”是指的数据的位置移动,或是将物理计划并行化的操作。一个“exchange”包含一个sender一个receiver,这使得数据可以在不同的节点间移动。

你可以在一个物理计划中用这种方式来参与Major fragments:你可以把物理计划导出到一个JSON文件中,手动修改它,并使用SUBMIT PLAN命令将这个json提交回Drill。你也可以在查询分析器中查看这些Major fragments,查询分析器可以通过Drill的WEB终端登入。请查询EXPLAIN和Query Profiles章节来获得更多信息。

Minor Fragments

每个Major Fragments 都可以并行化到一系列Minor Fragments;一个Minor Fragments是一个线程中运行的一个工作的逻辑单元。Drill中的一个逻辑工作单元,也被为一个”切片“。Drill 创建的执行计划,是由若干Minor Fragments组成的。Drill给每个Minor Fragments分配了一个MinorFragmentID;

在”接待员“drillbit中的”并行器“是负责从一个Major Fragment中创建出若干个Minor Fragments,做法就是将一个Major Fragment 打散成尽可能多的能在集群中同时运行的minor fragments.

Drill在单独的线程内运行Minor Fragments,并且尽可能地快(这要看它依赖的上游数据)。Drill会把Minor Fragments归划到拥有数据本地化的那些节点上运行。如果做不到,Drill会在当前可用的Drillbit中使用那个流行的Round-Robbin算法进行分配。

Minor Fragments 包含一个或多个关系运算符。每个运算符执行一个操作,比如scan,filter,join,或是group by。每个运行符都有一个操作类型和一个操作ID(operationID).每个操作ID定义了它和它所从属的Minor Fragment和关系。请查阅”物理操作符“章节。

例如,当执行两个文件的Hash聚合操作时,Drill将第一个阶段(扫行扫描文件的阶段)打散成两个Minor frametns,每个minor fragments 包含一个扫描文件的扫描运算符。Drill把那个专司于进行数据聚合的阶段打散成4个minor fragments,四个中的每一个都包含 一个专门对数据做hash聚合的Hash 运算符。

你不能修改执行计划中的minor fragments的数量。不过,你可以在Drill web console中查看Query profiler并修改能够改变minor fragments行为的一些配置,比如修改最大切片数。请查阅”选项配置“章节。

Minor Fragments的执行

Minor Fragments可以作为叶子fragment,根fragment和中间fragment来运行。一棵执行树只能有一个根fragment.整棵执行树上的协调是通过从根fragment开始的数字来进行的,根节点的数字是0.数据流从叶子fragment到根fragment一个个地往下流。

根fragment运行在“接待员”Drillbit上,他接受查询,从数据表中读取元数据,重写查询,并将查询路由到执行树中的下一层。其他的fragments会成为叶子fragments或是中间fragments。

中间fragment会在数据可用,或是其他fragment将数据喂过来的时候开始执行。它们在数据上执行操作,并把它们往下传。它们也会把聚合过的数据传给根fragment,根fragment又会做进一步的聚合操作或者是把查询结果提供给客户端或是应用程序。

叶子fragment并行地扫表,或者是和存储层打交道,或是是读本地磁盘数据。叶子fragments把中间结果回传给中间fragments,中间fragments会接着在这些中间结果上各种并行操作。

Drill只会规划那些可以并发执行的fragments的查询,例如,如果一个集群只有20个切片,Drill会在那个Major fragment中规划最多20个minor fragments。Dril会乐观地假定它能并发地执行任务。一个Major fragments中的minor framents由于共同的上游数据依赖,会于同一时间开始执行。