对于csv文件,很多人用excel打开它,然后用excel内置函数来操作数据。
我不喜欢界面化的东西,一般在linux shell里来操作这些数据。
对csv的处理,不管spark, hive, 还是drill, impala都是可以的,这些工具都提供了一个SQL引擎来访问csv,你可以编写sql语句来访问数据。
显然,drill是最方便的。其他工具有如下问题:
- Hive:要定义schema,并且依赖于HDFS,查询很慢
- Spark:体积比较庞大,它的SQL操作从dataframe转换而来
- Impala:依赖于Hive的metadata
相对来说,drill开箱即用,足够灵巧。它不需要定义schema,可以自由读取多种外部文件格式。虽然它也可以部署成分布式服务,但你只把它当作一个工具,用起来也很不错。
登陆linux服务器,运行drill-embedded打开本机的一个drill实例。然后,可以从浏览器访问drill的web管理端口:http://xx.xx.xx.xx:8047/
进入web页面后,稍微调整几个设置,让drill用起来更像Mysql。谁让我们都很熟悉Mysql呢?
如下图,在顶部Storage栏目,点击dfs的update按钮:
我们在这里定义本地文件系统的路径,以及目标文件(比如csv)的加载格式。
点击进去后,是一个Json文件,需要手工编辑这个Json文件。
首先在workspace里增加一节内容,对应用户的家目录的路径,这个路径用于放置输入文件。如下:
"workspaces": {
"tmp": {
"location": "/tmp",
"writable": true,
"defaultInputFormat": null,
"allowAccessOutsideWorkspace": false
},
"root": {
"location": "/",
"writable": false,
"defaultInputFormat": null,
"allowAccessOutsideWorkspace": false
},
"pyh": {
"location": "/home/pyh/tmp",
"writable": false,
"defaultInputFormat": null,
"allowAccessOutsideWorkspace": false
}
},
上述加粗的内容,就是新增的路径。这个路径,在drill里对应着database的概念。比如,在drill shell里,可以如下访问这个database:
use dfs.pyh;
这里的dfs是默认的存储插件名称,pyh就是数据库的名称。在drill里,路径对应着database名称,输入文件对应着table名称。
接着,继续编写上述Json,找到csv文件定义,修改如下:
"csv": {
"type": "text",
"extensions": [
"csv"
],
"extractHeader": true
},
上述加粗的字体,就是新增的。表示对于csv文件,可以infer header,也就是从输入文件的第一行去infer header。当然,这就要求输入的csv文件第一行包含header名称。
如果不做上述修改的话,drill里每行的输出就是一个数组,列的内容挤在这个数组里,不伦不类的。而修改后,drill就自动把每行按照csv的分隔符拆开,并且自动按拆开的内容组装成列,看起来跟Mysql一样。
现在回到drill shell,执行相应的查询,如下:
apache drill (dfs.pyh)> use dfs.pyh;
+------+-------------------------------------+
| ok | summary |
+------+-------------------------------------+
| true | Default schema changed to [dfs.pyh] |
+------+-------------------------------------+
1 row selected (0.122 seconds)
apache drill (dfs.pyh)> select * from `people.csv` limit 3;
+--------------+-----------+--------+---------+-----------------------------+
| name | born | sex | tel | job |
+--------------+-----------+--------+---------+-----------------------------+
| Romeo V.F. | 1973-4-10 | Male | 5158581 | Delivery Truck Driver |
| Preston D.I. | 1974-8-2 | Male | 3719958 | Home Health Aide |
| Ophelia D.A. | 1972-9-14 | Female | 9417846 | Maintenance & Repair Worker |
+--------------+-----------+--------+---------+-----------------------------+
3 rows selected (0.177 seconds)
你看,这就跟Mysql一模一样了。参考上篇博客,我们也可以执行更复杂的查询:
apache drill (dfs.pyh)> select job,count(*) as dd from `people.csv` group by job order by dd desc limit 10;
+--------------------------------------+-----+
| job | dd |
+--------------------------------------+-----+
| School Counselor | 231 |
| Customer Service Representative | 231 |
| Veterinary Technologist & Technician | 230 |
| Insurance Agent | 229 |
| Clinical Social Worker | 227 |
| Financial Advisor | 225 |
| Accountant | 225 |
| Carpenter | 223 |
| HR Specialist | 222 |
| Painter | 221 |
+--------------------------------------+-----+
10 rows selected (0.208 seconds)
因为drill的操作是内存映射,这个过程是很快的。当然,缺点是比较耗内存,一个drill实例,默认就要求4G内存,挺消耗资源。
对于csv的操作,spark也很快。但spark的确不如drill方便,它的SQL是基于dataframe的,要从dataframe才能生成一个sql对象。作为对比,spark的优势还在于对非结构化数据的处理(RDD引擎),以及流处理的能力。对于高度结构化数据,drill甚至更为强大。
而在SQL引擎表现上,drill和spark比较类似,性能也接近。各自都有一个优化器,负责sql语句解析与优化(逻辑计划、物理计划),以及执行规划。它们的执行规划甚至都是类似的,只是概念不同而已,如下表对比:
总体上,对于高度结构化的数据,drill是个不错的查询引擎,性能很好。稍微配置下,就跟传统的Mysql很像,用起来顺手。