前面已经讲过如何将log4j的日志输出到指定的hdfs目录,我们前面的指定目录为/flume/events。

如果想用Hive来分析采集来的日志,我们可以将/flume/events下面的日志数据都load到hive中的表当中去。

如果了解hive的load data原理的话,还有一种更简便的方式,可以省去load data这一步,就是直接将sink1.hdfs.path指定为hive表的目录。

下面我将详细描述具体的操作步骤。

我们还是从需求驱动来讲解,前面我们采集的数据,都是接口的访问日志数据,数据格式是JSON格式如下:

{"requestTime":1405651379758,"requestParams":{"timestamp":1405651377211,"phone":"02038824941","cardName":"测试商家名称","provinceCode":"440000","cityCode":"440106"},"requestUrl":"/reporter-api/reporter/reporter12/init.do"}

现在有一个需求,我们要统计接口的总调用量。

我第一想法就是,hive中建一张表:test             然后将hdfs.path指定为tier1.sinks.sink1.hdfs.path=hdfs://master68:8020/user/hive/warehouse/besttone.db/test

然后select  count(*) from test;   完事。

这个方案简单,粗暴,先这么干着。于是会遇到一个问题,我的日志数据时JSON格式的,需要hive来序列化和反序列化JSON格式的数据到test表的具体字段当中去。

这有点糟糕,因为hive本身没有提供JSON的SERDE,但是有提供函数来解析JSON字符串,

第一个是(UDF):

get_json_object(string json_string,string path) 从给定路径上的JSON字符串中抽取出JSON对象,并返回这个对象的JSON字符串形式,如果输入的JSON字符串是非法的,则返回NULL。

第二个是表生成函数(UDTF):json_tuple(string jsonstr,p1,p2,...,pn) 本函数可以接受多个标签名称,对输入的JSON字符串进行处理,这个和get_json_object这个UDF类似,不过更高效,其通过一次调用就可以获得多个键值,例:select b.* from test_json a lateral view json_tuple(a.id,'id','name') b as f1,f2;通过lateral view行转列。

最理想的方式就是能有一种JSON SERDE,只要我们LOAD完数据,就直接可以select * from test,而不是select get_json_object这种方式来获取,N个字段就要解析N次,效率太低了。

好在cloudrea wiki里提供了一个json serde类(这个类没有在发行的hive的jar包中),于是我把它搬来了,如下:

[java] view plaincopy
  1. package com.besttone.hive.serde;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.Properties;
  8. import org.apache.hadoop.conf.Configuration;
  9. import org.apache.hadoop.hive.serde.serdeConstants;
  10. import org.apache.hadoop.hive.serde2.SerDe;
  11. import org.apache.hadoop.hive.serde2.SerDeException;
  12. import org.apache.hadoop.hive.serde2.SerDeStats;
  13. import org.apache.hadoop.hive.serde2.objectinspector.ListObjectInspector;
  14. import org.apache.hadoop.hive.serde2.objectinspector.MapObjectInspector;
  15. import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
  16. import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
  17. import org.apache.hadoop.hive.serde2.objectinspector.StructField;
  18. import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
  19. import org.apache.hadoop.hive.serde2.typeinfo.ListTypeInfo;
  20. import org.apache.hadoop.hive.serde2.typeinfo.MapTypeInfo;
  21. import org.apache.hadoop.hive.serde2.typeinfo.StructTypeInfo;
  22. import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
  23. import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
  24. import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoUtils;
  25. import org.apache.hadoop.io.Text;
  26. import org.apache.hadoop.io.Writable;
  27. import org.codehaus.jackson.map.ObjectMapper;
  28. /**
  29. * This SerDe can be used for processing JSON data in Hive. It supports
  30. * arbitrary JSON data, and can handle all Hive types except for UNION. However,
  31. * the JSON data is expected to be a series of discrete records, rather than a
  32. * JSON array of objects.
  33. *
  34. * The Hive table is expected to contain columns with names corresponding to
  35. * fields in the JSON data, but it is not necessary for every JSON field to have
  36. * a corresponding Hive column. Those JSON fields will be ignored during
  37. * queries.
  38. *
  39. * Example:
  40. *
  41. * { "a": 1, "b": [ "str1", "str2" ], "c": { "field1": "val1" } }
  42. *
  43. * Could correspond to a table:
  44. *
  45. * CREATE TABLE foo (a INT, b ARRAY<STRING>, c STRUCT<field1:STRING>);
  46. *
  47. * JSON objects can also interpreted as a Hive MAP type, so long as the keys and
  48. * values in the JSON object are all of the appropriate types. For example, in
  49. * the JSON above, another valid table declaraction would be:
  50. *
  51. * CREATE TABLE foo (a INT, b ARRAY<STRING>, c MAP<STRING,STRING>);
  52. *
  53. * Only STRING keys are supported for Hive MAPs.
  54. */
  55. public class JSONSerDe implements SerDe {
  56. private StructTypeInfo rowTypeInfo;
  57. private ObjectInspector rowOI;
  58. private List<String> colNames;
  59. private List<Object> row = new ArrayList<Object>();
  60. //遇到非JSON格式输入的时候的处理。
  61. private boolean ignoreInvalidInput;
  62. /**
  63. * An initialization function used to gather information about the table.
  64. * Typically, a SerDe implementation will be interested in the list of
  65. * column names and their types. That information will be used to help
  66. * perform actual serialization and deserialization of data.
  67. */
  68. @Override
  69. public void initialize(Configuration conf, Properties tbl)
  70. throws SerDeException {
  71. // 遇到无法转换成JSON对象的字符串时,是否忽略,默认不忽略,抛出异常,设置为true将跳过异常。
  72. ignoreInvalidInput = Boolean.valueOf(tbl.getProperty(
  73. "input.invalid.ignore", "false"));
  74. // Get a list of the table's column names.
  75. String colNamesStr = tbl.getProperty(serdeConstants.LIST_COLUMNS);
  76. colNames = Arrays.asList(colNamesStr.split(","));
  77. // Get a list of TypeInfos for the columns. This list lines up with
  78. // the list of column names.
  79. String colTypesStr = tbl.getProperty(serdeConstants.LIST_COLUMN_TYPES);
  80. List<TypeInfo> colTypes = TypeInfoUtils
  81. .getTypeInfosFromTypeString(colTypesStr);
  82. rowTypeInfo = (StructTypeInfo) TypeInfoFactory.getStructTypeInfo(
  83. colNames, colTypes);
  84. rowOI = TypeInfoUtils
  85. .getStandardJavaObjectInspectorFromTypeInfo(rowTypeInfo);
  86. }
  87. /**
  88. * This method does the work of deserializing a record into Java objects
  89. * that Hive can work with via the ObjectInspector interface. For this
  90. * SerDe, the blob that is passed in is a JSON string, and the Jackson JSON
  91. * parser is being used to translate the string into Java objects.
  92. *
  93. * The JSON deserialization works by taking the column names in the Hive
  94. * table, and looking up those fields in the parsed JSON object. If the
  95. * value of the field is not a primitive, the object is parsed further.
  96. */
  97. @Override
  98. public Object deserialize(Writable blob) throws SerDeException {
  99. Map<?, ?> root = null;
  100. row.clear();
  101. try {
  102. ObjectMapper mapper = new ObjectMapper();
  103. // This is really a Map<String, Object>. For more information about
  104. // how
  105. // Jackson parses JSON in this example, see
  106. // http://wiki.fasterxml.com/JacksonDataBinding
  107. root = mapper.readValue(blob.toString(), Map.class);
  108. } catch (Exception e) {
  109. // 如果为true,不抛出异常,忽略该行数据
  110. if (!ignoreInvalidInput)
  111. throw new SerDeException(e);
  112. else {
  113. return null;
  114. }
  115. }
  116. // Lowercase the keys as expected by hive
  117. Map<String, Object> lowerRoot = new HashMap();
  118. for (Map.Entry entry : root.entrySet()) {
  119. lowerRoot.put(((String) entry.getKey()).toLowerCase(),
  120. entry.getValue());
  121. }
  122. root = lowerRoot;
  123. Object value = null;
  124. for (String fieldName : rowTypeInfo.getAllStructFieldNames()) {
  125. try {
  126. TypeInfo fieldTypeInfo = rowTypeInfo
  127. .getStructFieldTypeInfo(fieldName);
  128. value = parseField(root.get(fieldName), fieldTypeInfo);
  129. } catch (Exception e) {
  130. value = null;
  131. }
  132. row.add(value);
  133. }
  134. return row;
  135. }
  136. /**
  137. * Parses a JSON object according to the Hive column's type.
  138. *
  139. * @param field
  140. *            - The JSON object to parse
  141. * @param fieldTypeInfo
  142. *            - Metadata about the Hive column
  143. * @return - The parsed value of the field
  144. */
  145. private Object parseField(Object field, TypeInfo fieldTypeInfo) {
  146. switch (fieldTypeInfo.getCategory()) {
  147. case PRIMITIVE:
  148. // Jackson will return the right thing in this case, so just return
  149. // the object
  150. if (field instanceof String) {
  151. field = field.toString().replaceAll("\n", "\\\\n");
  152. }
  153. return field;
  154. case LIST:
  155. return parseList(field, (ListTypeInfo) fieldTypeInfo);
  156. case MAP:
  157. return parseMap(field, (MapTypeInfo) fieldTypeInfo);
  158. case STRUCT:
  159. return parseStruct(field, (StructTypeInfo) fieldTypeInfo);
  160. case UNION:
  161. // Unsupported by JSON
  162. default:
  163. return null;
  164. }
  165. }
  166. /**
  167. * Parses a JSON object and its fields. The Hive metadata is used to
  168. * determine how to parse the object fields.
  169. *
  170. * @param field
  171. *            - The JSON object to parse
  172. * @param fieldTypeInfo
  173. *            - Metadata about the Hive column
  174. * @return - A map representing the object and its fields
  175. */
  176. private Object parseStruct(Object field, StructTypeInfo fieldTypeInfo) {
  177. Map<Object, Object> map = (Map<Object, Object>) field;
  178. ArrayList<TypeInfo> structTypes = fieldTypeInfo
  179. .getAllStructFieldTypeInfos();
  180. ArrayList<String> structNames = fieldTypeInfo.getAllStructFieldNames();
  181. List<Object> structRow = new ArrayList<Object>(structTypes.size());
  182. for (int i = 0; i < structNames.size(); i++) {
  183. structRow.add(parseField(map.get(structNames.get(i)),
  184. structTypes.get(i)));
  185. }
  186. return structRow;
  187. }
  188. /**
  189. * Parse a JSON list and its elements. This uses the Hive metadata for the
  190. * list elements to determine how to parse the elements.
  191. *
  192. * @param field
  193. *            - The JSON list to parse
  194. * @param fieldTypeInfo
  195. *            - Metadata about the Hive column
  196. * @return - A list of the parsed elements
  197. */
  198. private Object parseList(Object field, ListTypeInfo fieldTypeInfo) {
  199. ArrayList<Object> list = (ArrayList<Object>) field;
  200. TypeInfo elemTypeInfo = fieldTypeInfo.getListElementTypeInfo();
  201. for (int i = 0; i < list.size(); i++) {
  202. list.set(i, parseField(list.get(i), elemTypeInfo));
  203. }
  204. return list.toArray();
  205. }
  206. /**
  207. * Parse a JSON object as a map. This uses the Hive metadata for the map
  208. * values to determine how to parse the values. The map is assumed to have a
  209. * string for a key.
  210. *
  211. * @param field
  212. *            - The JSON list to parse
  213. * @param fieldTypeInfo
  214. *            - Metadata about the Hive column
  215. * @return
  216. */
  217. private Object parseMap(Object field, MapTypeInfo fieldTypeInfo) {
  218. Map<Object, Object> map = (Map<Object, Object>) field;
  219. TypeInfo valueTypeInfo = fieldTypeInfo.getMapValueTypeInfo();
  220. for (Map.Entry<Object, Object> entry : map.entrySet()) {
  221. map.put(entry.getKey(), parseField(entry.getValue(), valueTypeInfo));
  222. }
  223. return map;
  224. }
  225. /**
  226. * Return an ObjectInspector for the row of data
  227. */
  228. @Override
  229. public ObjectInspector getObjectInspector() throws SerDeException {
  230. return rowOI;
  231. }
  232. /**
  233. * Unimplemented
  234. */
  235. @Override
  236. public SerDeStats getSerDeStats() {
  237. return null;
  238. }
  239. /**
  240. * JSON is just a textual representation, so our serialized class is just
  241. * Text.
  242. */
  243. @Override
  244. public Class<? extends Writable> getSerializedClass() {
  245. return Text.class;
  246. }
  247. /**
  248. * This method takes an object representing a row of data from Hive, and
  249. * uses the ObjectInspector to get the data for each column and serialize
  250. * it. This implementation deparses the row into an object that Jackson can
  251. * easily serialize into a JSON blob.
  252. */
  253. @Override
  254. public Writable serialize(Object obj, ObjectInspector oi)
  255. throws SerDeException {
  256. Object deparsedObj = deparseRow(obj, oi);
  257. ObjectMapper mapper = new ObjectMapper();
  258. try {
  259. // Let Jackson do the work of serializing the object
  260. return new Text(mapper.writeValueAsString(deparsedObj));
  261. } catch (Exception e) {
  262. throw new SerDeException(e);
  263. }
  264. }
  265. /**
  266. * Deparse a Hive object into a Jackson-serializable object. This uses the
  267. * ObjectInspector to extract the column data.
  268. *
  269. * @param obj
  270. *            - Hive object to deparse
  271. * @param oi
  272. *            - ObjectInspector for the object
  273. * @return - A deparsed object
  274. */
  275. private Object deparseObject(Object obj, ObjectInspector oi) {
  276. switch (oi.getCategory()) {
  277. case LIST:
  278. return deparseList(obj, (ListObjectInspector) oi);
  279. case MAP:
  280. return deparseMap(obj, (MapObjectInspector) oi);
  281. case PRIMITIVE:
  282. return deparsePrimitive(obj, (PrimitiveObjectInspector) oi);
  283. case STRUCT:
  284. return deparseStruct(obj, (StructObjectInspector) oi, false);
  285. case UNION:
  286. // Unsupported by JSON
  287. default:
  288. return null;
  289. }
  290. }
  291. /**
  292. * Deparses a row of data. We have to treat this one differently from other
  293. * structs, because the field names for the root object do not match the
  294. * column names for the Hive table.
  295. *
  296. * @param obj
  297. *            - Object representing the top-level row
  298. * @param structOI
  299. *            - ObjectInspector for the row
  300. * @return - A deparsed row of data
  301. */
  302. private Object deparseRow(Object obj, ObjectInspector structOI) {
  303. return deparseStruct(obj, (StructObjectInspector) structOI, true);
  304. }
  305. /**
  306. * Deparses struct data into a serializable JSON object.
  307. *
  308. * @param obj
  309. *            - Hive struct data
  310. * @param structOI
  311. *            - ObjectInspector for the struct
  312. * @param isRow
  313. *            - Whether or not this struct represents a top-level row
  314. * @return - A deparsed struct
  315. */
  316. private Object deparseStruct(Object obj, StructObjectInspector structOI,
  317. boolean isRow) {
  318. Map<Object, Object> struct = new HashMap<Object, Object>();
  319. List<? extends StructField> fields = structOI.getAllStructFieldRefs();
  320. for (int i = 0; i < fields.size(); i++) {
  321. StructField field = fields.get(i);
  322. // The top-level row object is treated slightly differently from
  323. // other
  324. // structs, because the field names for the row do not correctly
  325. // reflect
  326. // the Hive column names. For lower-level structs, we can get the
  327. // field
  328. // name from the associated StructField object.
  329. String fieldName = isRow ? colNames.get(i) : field.getFieldName();
  330. ObjectInspector fieldOI = field.getFieldObjectInspector();
  331. Object fieldObj = structOI.getStructFieldData(obj, field);
  332. struct.put(fieldName, deparseObject(fieldObj, fieldOI));
  333. }
  334. return struct;
  335. }
  336. /**
  337. * Deparses a primitive type.
  338. *
  339. * @param obj
  340. *            - Hive object to deparse
  341. * @param oi
  342. *            - ObjectInspector for the object
  343. * @return - A deparsed object
  344. */
  345. private Object deparsePrimitive(Object obj, PrimitiveObjectInspector primOI) {
  346. return primOI.getPrimitiveJavaObject(obj);
  347. }
  348. private Object deparseMap(Object obj, MapObjectInspector mapOI) {
  349. Map<Object, Object> map = new HashMap<Object, Object>();
  350. ObjectInspector mapValOI = mapOI.getMapValueObjectInspector();
  351. Map<?, ?> fields = mapOI.getMap(obj);
  352. for (Map.Entry<?, ?> field : fields.entrySet()) {
  353. Object fieldName = field.getKey();
  354. Object fieldObj = field.getValue();
  355. map.put(fieldName, deparseObject(fieldObj, mapValOI));
  356. }
  357. return map;
  358. }
  359. /**
  360. * Deparses a list and its elements.
  361. *
  362. * @param obj
  363. *            - Hive object to deparse
  364. * @param oi
  365. *            - ObjectInspector for the object
  366. * @return - A deparsed object
  367. */
  368. private Object deparseList(Object obj, ListObjectInspector listOI) {
  369. List<Object> list = new ArrayList<Object>();
  370. List<?> field = listOI.getList(obj);
  371. ObjectInspector elemOI = listOI.getListElementObjectInspector();
  372. for (Object elem : field) {
  373. list.add(deparseObject(elem, elemOI));
  374. }
  375. return list;
  376. }
  377. }

我稍微修改了一点东西,多加了一个参数input.invalid.ignore,对应的变量为:

//遇到非JSON格式输入的时候的处理。
private boolean ignoreInvalidInput;

在deserialize方法中原来是如果传入的是非JSON格式字符串的话,直接抛出了SerDeException,我加了一个参数来控制它是否抛出异常,在initialize方法中初始化这个变量(默认为false):

// 遇到无法转换成JSON对象的字符串时,是否忽略,默认不忽略,抛出异常,设置为true将跳过异常。
ignoreInvalidInput = Boolean.valueOf(tbl.getProperty(
"input.invalid.ignore", "false"));

好的,现在将这个类打成JAR包: JSONSerDe.jar,放在hive_home的auxlib目录下(我的是/etc/hive/auxlib),然后修改hive-env.sh,添加HIVE_AUX_JARS_PATH=/etc/hive/auxlib/JSONSerDe.jar,这样每次运行hive客户端的时候都会将这个jar包添加到classpath,否则在设置SERDE的时候会报找不到类。

现在我们在HIVE中创建一张表用来存放日志数据:

[plain] view plaincopy
  1. create table test(
  2. requestTime BIGINT,
  3. requestParams STRUCT<timestamp:BIGINT,phone:STRING,cardName:STRING,provinceCode:STRING,cityCode:STRING>,
  4. requestUrl STRING)
  5. row format serde "com.besttone.hive.serde.JSONSerDe"
  6. WITH SERDEPROPERTIES(
  7. "input.invalid.ignore"="true",
  8. "requestTime"="$.requestTime",
  9. "requestParams.timestamp"="$.requestParams.timestamp",
  10. "requestParams.phone"="$.requestParams.phone",
  11. "requestParams.cardName"="$.requestParams.cardName",
  12. "requestParams.provinceCode"="$.requestParams.provinceCode",
  13. "requestParams.cityCode"="$.requestParams.cityCode",
  14. "requestUrl"="$.requestUrl");

这个表结构就是按照日志格式设计的,还记得前面说过的日志数据如下:

{"requestTime":1405651379758,"requestParams":{"timestamp":1405651377211,"phone":"02038824941","cardName":"测试商家名称","provinceCode":"440000","cityCode":"440106"},"requestUrl":"/reporter-api/reporter/reporter12/init.do"}

我使用了一个STRUCT类型来保存requestParams的值,row format我们用的是自定义的json serde:com.besttone.hive.serde.JSONSerDe,SERDEPROPERTIES中,除了设置JSON对象的映射关系外,我还设置了一个自定义的参数:"input.invalid.ignore"="true",忽略掉所有非JSON格式的输入行。这里不是真正意义的忽略,只是非法行的每个输出字段都为NULL了,要在结果集上忽略,必须这样写:select * from test where requestUrl is not null;

OK表建好了,现在就差数据了,我们启动flumedemo的WriteLog,往hive表test目录下面输出一些日志数据,然后在进入hive客户端,select * from test;所以字段都正确的解析,大功告成。

flume.conf如下:

[plain] view plaincopy
  1. tier1.sources=source1
  2. tier1.channels=channel1
  3. tier1.sinks=sink1
  4. tier1.sources.source1.type=avro
  5. tier1.sources.source1.bind=0.0.0.0
  6. tier1.sources.source1.port=44444
  7. tier1.sources.source1.channels=channel1
  8. tier1.sources.source1.interceptors=i1 i2
  9. tier1.sources.source1.interceptors.i1.type=regex_filter
  10. tier1.sources.source1.interceptors.i1.regex=\\{.*\\}
  11. tier1.sources.source1.interceptors.i2.type=timestamp
  12. tier1.channels.channel1.type=memory
  13. tier1.channels.channel1.capacity=10000
  14. tier1.channels.channel1.transactionCapacity=1000
  15. tier1.channels.channel1.keep-alive=30
  16. tier1.sinks.sink1.type=hdfs
  17. tier1.sinks.sink1.channel=channel1
  18. tier1.sinks.sink1.hdfs.path=hdfs://master68:8020/user/hive/warehouse/besttone.db/test
  19. tier1.sinks.sink1.hdfs.fileType=DataStream
  20. tier1.sinks.sink1.hdfs.writeFormat=Text
  21. tier1.sinks.sink1.hdfs.rollInterval=0
  22. tier1.sinks.sink1.hdfs.rollSize=10240
  23. tier1.sinks.sink1.hdfs.rollCount=0
  24. tier1.sinks.sink1.hdfs.idleTimeout=60

besttone.db是我在hive中创建的数据库,了解hive的应该理解没多大问题。

OK,到这篇文章为止,整个从LOG4J生产日志,到flume收集日志,再到用hive离线分析日志,一整套流水线都讲解完了。

flume学习(五):使用hive来分析flume收集的日志数据相关推荐

  1. 蓝牙学习五(广播包分析wireshark)

    1.简介 软件工具:wireshark 硬件抓包工具:nrf52840 dongle 2.数据包分析 使用wireshark抓到的数据包分为两个部分,一部分是软件自己添加的内容,另一部分才是广播出来的 ...

  2. 大数据相关书籍(包含Java, Scala, R, Linux, Spark, Hadoop, Hive, Hbase, Sqoop, Flume, Strom)

    下面书单,有一部分英文版原版,当然价格也相对高一点,英文版部分需要在在亚马逊搜索 ,中文版大部分在京东有售! <Hadoop核心技术> 翟周伟 著 <Storm分布式实时计算模式 & ...

  3. 学习笔记Hive(五) —— Hive应用(3)—— Hive查询

    五.Hive查询 5.1.创建职工信息表 任务实现: 1.创建表dept,emp和salgrade 2.导入数据 将数据emp.txt导入到表emp #emp.txt 7369,SMITH,CLERK ...

  4. flume学习-含安装

    1.Flume是什么:Flume是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集.聚合和传输的系统.Flume基于流式架构,灵活简单. Flume组成架构 下面我们来详细介绍一下F ...

  5. BT源代码学习心得(十五):客户端源代码分析(下载过程中的块选取策略)

    BT源代码学习心得(十五):客户端源代码分析(下载过程中的块选取策略) 发信人: wolfenstein (NeverSayNever), 个人文集 标  题: BT源代码学习心得(十五):客户端源代 ...

  6. flume学习(四):Flume Interceptors的使用

    对于flume拦截器,我的理解是:在app(应用程序日志)和 source 之间的,对app日志进行拦截处理的.也即在日志进入到source之前,对日志进行一些包装.清新过滤等等动作. 官方上提供的已 ...

  7. flume学习之一 是什么,主要应用在什么场景

    1.Flume是什么? Flume是Cloudera开发的一个高可用的,高可靠的,分布式的海量日志采集.聚合和传输的系统,Flume支持在日志系统中定制各类数据发送方,用于收集数据.数据源可定制.可扩 ...

  8. hive 修改分桶数 分桶表_hive 学习之路(五)、Hive的分区表与分桶表

    Hive将表划分为分区(partition)表和分桶(bucket)表. 分区可以让数据的部分查询变得更快,也就是说,在加载数据的时候可以指定加载某一部分数据,并不是全量的数据. 分桶表通常是在原始数 ...

  9. 大数据学习之路-Hive

    Hive 1. Hive基本概念 1.1 什么是Hive 1.2 Hive的优缺点 1.2.1 优点 1.2.2 缺点 1.3 Hive架构原理 1.4 Hive和 数据库比较 1.4.1 查询语言 ...

  10. 五万字 | Hive知识体系保姆级教程

    文档目录如下: Hive涉及的知识点如下图所示,本文将逐一讲解: 本文较长,获取本文完整PDF文档,请扫码关注公众号[五分钟学大数据],后台发送:hive pdf,即可下载带目录的完整版Hive文档: ...

最新文章

  1. operator did not match Pytorch‘s Interpolation until opset 11
  2. 每日一题题目6:二分查找
  3. NHibernate.Validator 实体验证框架
  4. 1002:输出第二个整数
  5. JavaScript 几种排序算法实现(冒泡、选择、插入、归并、快速排序)
  6. linux 编译3g驱动_linux下使用3G拨号上网 以及3g驱动设置
  7. Swipper.js实现轮播功能
  8. LeetCode 525. 连续数组(前缀和+哈希)
  9. php angular使用,如何使用angular.js PHP从mysql显示数据?
  10. MSSQL2008如何关闭代码智能提示?
  11. 赫夫曼树的定义及原理
  12. Iphone 铃声制作及同步
  13. JavaScript基础复习下(51st)
  14. java now_Java LocalDateTime now()用法及代码示例
  15. 服务器的正向代理与反向代理
  16. 非聚集索引中的临界点(Tipping Point)
  17. win10电脑wifi显示无法连接服务器,Win10怎么连Wifi?解决Win10无法连接wifi无线网络的方法图文详解...
  18. 软件:汽车的灵魂操盘手
  19. pytest与coverage联合使用
  20. Linux操作系统应用

热门文章

  1. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_04 IO字节流_11_字节输入流一次读取多个字节...
  2. iphone移动端踩坑
  3. 多进程——守护进程例子
  4. 用VAE(variational autoencoder)做sentence embedding/representation或者其他任何结构数据的热presentation...
  5. PHP验证时有用的几段代码
  6. js函数中变量声明提前
  7. Swift给每个开发者赢取500万的机会!不看一生后悔。
  8. AspNet2.0的QuickStart出了
  9. Elasticsearch 系列4 --- Windows10安装Kibana
  10. vm centos 网络配置