<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Data Engineering Blog</title>
    <link>https://taaewoo.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 19 May 2026 07:29:52 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Taaewoo</managingEditor>
    <image>
      <title>Data Engineering Blog</title>
      <url>https://tistory1.daumcdn.net/tistory/3978336/attach/1948ea69a5044a2d8e93f1bc84c693e8</url>
      <link>https://taaewoo.tistory.com</link>
    </image>
    <item>
      <title>Riot Data Pipeline 구축하기 #7 - HDFS에 저장된 JSON 데이터로 Hive 테이블 생성하기</title>
      <link>https://taaewoo.tistory.com/81</link>
      <description>&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Riot 데이터를 수집해서 최종적으로 HDFS에 저장하는 과정까지 성공했습니다( 비록 미흡한 점이 상당히 많지만.... ). 이제는 저장된 데이터를 기반으로 Hive 테이블을 생성하는 과정을 진행하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Docker Compose에 Hive 서비스 추가&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Kafka에 있는 데이터를 HDFS에 저장하기 위해 Docker Compose에 Spark와 HDFS 서비스들을 추가했었습니다. 이번에는 동일한 Docker Compose에 Hive 서비스를 추가하겠습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;b&gt;docker-compose.yml&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #800000;&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;'2'&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; services&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; spark-master&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/spark-master:2.4.0-hadoop2.8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;8080:8080&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;7077:7077&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;environment&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;INIT_DAEMON_STEP=setup_spark&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; spark-worker-1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/spark-worker:2.4.0-hadoop2.8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;depends_on&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;spark-master&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;8081:8081&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;environment&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;SPARK_MASTER=spark://spark-master:7077&quot;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; spark-notebook&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/spark-notebook:2.1.0-hadoop2.8-hive&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;container_name&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;spark-notebook&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;9001:9001&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; namenode&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/hadoop-namenode:1.1.0-hadoop2.8-java8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;container_name&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;namenode&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;volumes&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./data/namenode:/hadoop/dfs/name&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;environment&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;CLUSTER_NAME=test&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;50070:50070&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; datanode&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/hadoop-datanode:1.1.0-hadoop2.8-java8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;depends_on&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;namenode&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;volumes&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./data/datanode:/hadoop/dfs/data&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;50075:50075&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; hive-server&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/hive:2.3.2-postgresql-metastore&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;volumes&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hive_dir:/root&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;environment&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;HIVE_CORE_CONF_javax_jdo_option_ConnectionURL&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;jdbc:postgresql://hive-metastore/metastore&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;SERVICE_PRECONDITION&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;hive-metastore:9083&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;10000:10000&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;8000:8000&quot;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; hive-metastore&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/hive:2.3.2-postgresql-metastore&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;olor: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;command&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;/opt/hive/bin/hive --service metastore&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;bcolor: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;environment&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;SERVICE_PRECONDITION&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;namenode:50070 datanode:50075 hive-metastore-postgresql:5432&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;9083:9083&quot;&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; hive-metastore-postgresql&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;bcolor: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/hive-metastore-postgresql:2.3.0&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Match 데이터 경로 수정&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이전 글에서 Match 데이터를 저장한 HDFS 경로는 &quot;/riot/match_raw_data&quot; 였습니다. 하지만 데이터가 계속해서 쌓이면서 성능의 이슈를 생각한다면 Hive 테이블의 partition이 필요할 것입니다. 그래서 닉네임을 기준으로 partition을 구분하겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;만약 닉네임이 &quot;aaa&quot;라면 경로는 &quot;/riot/match_raw_data/name=aaa&quot;가 될 것입니다. 해당 파티션으로 데이터를 옮긴 후 결과는 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj7Vzd/btscMHz0qv8/LhIvkQkRsv7amEDydqPwdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj7Vzd/btscMHz0qv8/LhIvkQkRsv7amEDydqPwdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj7Vzd/btscMHz0qv8/LhIvkQkRsv7amEDydqPwdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj7Vzd%2FbtscMHz0qv8%2FLhIvkQkRsv7amEDydqPwdk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;850&quot; height=&quot;186&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Match 데이터 Hive 테이블 생성&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;데이터는 모두 준비되었으니 이제 테이블을 생성하겠습니다. Hive 테이블 생성 시 Json 파일을 기반으로 한다면 JsonSerDe 형식으로 지정할 수 있습니다. 하지만 문제는 따로 있습니다. Riot Match 데이터의 경우 모든 키 값의 갯수가 약 300개 이상입니다. 테이블 생성 쿼리를 사용할 때 Json 구조에 맞는 column 명시가 필수적입니다. 300개 이상의 column 값들을 모두 적는 것은 상당히 어렵고 시간 낭비라고 생각합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이러한 문제를 해결한 내용이 있으니 이 글을 참고하시기 바랍니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://taaewoo.tistory.com/76&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Hive] Complex Json 데이터 테이블 생성하기 (Json SerDe)&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1682449249206&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Hive] Complex Json 데이터 테이블 생성하기 (Json SerDe)&quot; data-og-description=&quot;Json 데이터를 사용하다보면 Json의 스키마 자체가 상당히 복잡하고 거대한 경우가 있습니다. 이번 글에서는 complex Json 데이터를 이용해 Hive 테이블을 생성하는 방법에 대해 소개하겠습니다. Json &quot; data-og-host=&quot;taaewoo.tistory.com&quot; data-og-source-url=&quot;https://taaewoo.tistory.com/76&quot; data-og-url=&quot;https://taaewoo.tistory.com/76&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/c4S9AV/hySpwEjOOH/UU9F9t1EkUwBEqKvFNzdvk/img.png?width=317&amp;amp;height=317&amp;amp;face=0_0_317_317,https://scrap.kakaocdn.net/dn/17Fd6/hySpLao4EW/FUOkgGnxmRMqHsxoEcW1F0/img.png?width=317&amp;amp;height=317&amp;amp;face=0_0_317_317,https://scrap.kakaocdn.net/dn/bVSEJG/hySpEWETmY/tqdaoOH9cmQGUKHKUfxtt0/img.png?width=1322&amp;amp;height=778&amp;amp;face=0_0_1322_778&quot;&gt;&lt;a href=&quot;https://taaewoo.tistory.com/76&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://taaewoo.tistory.com/76&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/c4S9AV/hySpwEjOOH/UU9F9t1EkUwBEqKvFNzdvk/img.png?width=317&amp;amp;height=317&amp;amp;face=0_0_317_317,https://scrap.kakaocdn.net/dn/17Fd6/hySpLao4EW/FUOkgGnxmRMqHsxoEcW1F0/img.png?width=317&amp;amp;height=317&amp;amp;face=0_0_317_317,https://scrap.kakaocdn.net/dn/bVSEJG/hySpEWETmY/tqdaoOH9cmQGUKHKUfxtt0/img.png?width=1322&amp;amp;height=778&amp;amp;face=0_0_1322_778');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Hive] Complex Json 데이터 테이블 생성하기 (Json SerDe)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Json 데이터를 사용하다보면 Json의 스키마 자체가 상당히 복잡하고 거대한 경우가 있습니다. 이번 글에서는 complex Json 데이터를 이용해 Hive 테이블을 생성하는 방법에 대해 소개하겠습니다. Json&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;taaewoo.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위의 글을 참고해 Hive 테이블 생성 쿼리를 자동으로 추출하면 아래와 같습니다. Partition과 해당 파일의 Location 값을 추가로 적었습니다. Column은 실제로 3개밖에 없지만 아주 복잡한 Json 구조입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1682449437896&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;create external table riot.match_raw(
  info struct&amp;lt;gamecreation:bigint, gameduration:int, gameendtimestamp:bigint, gameid:bigint, ...
  metadata struct&amp;lt;dataversion:string, matchid:string, participants:array&amp;lt;string&amp;gt;&amp;gt;,
  whosematch string)
PARTITIONED BY (name STRING)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 'hdfs://namenode:8020/riot/match_raw_data';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;쿼리를 실행했을 때 정상적으로 수행된 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1543&quot; data-origin-height=&quot;854&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0n1cE/btsczLxTUl0/FvjG8hZcGw4g9W9Kdmsdy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0n1cE/btsczLxTUl0/FvjG8hZcGw4g9W9Kdmsdy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0n1cE/btsczLxTUl0/FvjG8hZcGw4g9W9Kdmsdy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0n1cE%2FbtsczLxTUl0%2FFvjG8hZcGw4g9W9Kdmsdy0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1543&quot; height=&quot;854&quot; data-origin-width=&quot;1543&quot; data-origin-height=&quot;854&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;msck repair 명령어로 데이터 동기화 후 테이블을 조회해보면 아래와 같습니다. Json 구조가 워낙 복잡해 파악하기 어렵지만 확대하시면 더 자세하게 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;575&quot; data-origin-height=&quot;98&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1gC47/btscGUVaOul/9kSB8e4ofCFSohNmPtrdr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1gC47/btscGUVaOul/9kSB8e4ofCFSohNmPtrdr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1gC47/btscGUVaOul/9kSB8e4ofCFSohNmPtrdr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1gC47%2FbtscGUVaOul%2F9kSB8e4ofCFSohNmPtrdr0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;575&quot; height=&quot;98&quot; data-origin-width=&quot;575&quot; data-origin-height=&quot;98&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2654&quot; data-origin-height=&quot;707&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRZOC9/btscIKxv7D1/X4vChG0HQVrkUJU3emDFy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRZOC9/btscIKxv7D1/X4vChG0HQVrkUJU3emDFy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRZOC9/btscIKxv7D1/X4vChG0HQVrkUJU3emDFy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRZOC9%2FbtscIKxv7D1%2FX4vChG0HQVrkUJU3emDFy0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2654&quot; height=&quot;707&quot; data-origin-width=&quot;2654&quot; data-origin-height=&quot;707&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;다음 글에서는 이 데이터를 활용하는 과정에 대해 소개하도록 하겠습니다.&lt;/p&gt;</description>
      <category>BigData Engineering/Riot Data Pipeline</category>
      <category>Data Pipeline</category>
      <category>hdfs</category>
      <category>Hive</category>
      <category>json</category>
      <category>Riot</category>
      <category>테이블 생성</category>
      <author>Taaewoo</author>
      <guid isPermaLink="true">https://taaewoo.tistory.com/81</guid>
      <comments>https://taaewoo.tistory.com/81#entry81comment</comments>
      <pubDate>Wed, 26 Apr 2023 04:18:55 +0900</pubDate>
    </item>
    <item>
      <title>[HDFS] JMX Metrics 값 불러오기</title>
      <link>https://taaewoo.tistory.com/80</link>
      <description>&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Hadoop의 HDFS를 사용하다보면 현재 HDFS의 사용량을 여러가지 방법들로 확인합니다. 예를 들어 NameNode의 Web UI를 접속해 확인하거나 Ambari와 같은 배포판 관리 시스템에서도 쉽게 확인할 수 있습니다. 그런데 만약 모니터링 시스템을 직접 개발해서 사용한다면 코드 상에서 어떻게 HDFS의 정보를 가져올 수 있을까요? 이 방법에 대해 소개해드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;NameNode Web UI&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;우리가 흔히 원하는 HDFS 정보들은 NameNode Web UI에서 모두 제공을 하고있습니다. 보통 NameNode의 50070 포트로 쉽게 접속할 수 있습니다. ( http://{NameNode}:50070 )&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;791&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tx4MC/btr6eWyLhGu/ve3cQQg0VdT8wGXB9X5eak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tx4MC/btr6eWyLhGu/ve3cQQg0VdT8wGXB9X5eak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tx4MC/btr6eWyLhGu/ve3cQQg0VdT8wGXB9X5eak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ftx4MC%2Fbtr6eWyLhGu%2Fve3cQQg0VdT8wGXB9X5eak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;852&quot; height=&quot;791&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;791&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;NameNode JMX&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;&amp;nbsp;위의 NameNode Web UI는 HDFS 정보들을 어디서 가져오는 것일까요?&lt;/span&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;구글링을 여러가지 키워드로 검색해봤지만 원하는 답을 알 수 없었습니다.&lt;/span&gt;&lt;/b&gt; 그래서 결국 NameNode Web 소스 코드를 확인해봤습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위의 GUI에서 제가 원하는 정보인 &quot;DFS Used&quot;를 Hadoop Github에서 검색해 html 파일을 찾았습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/apache/hadoop&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/apache/hadoop&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;dfshealth.html&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1679935480137&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{#nn}
&amp;lt;table class=&quot;table table-bordered table-striped&quot;&amp;gt;
  &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt; Configured Capacity:&amp;lt;/th&amp;gt;&amp;lt;td&amp;gt;{Total|fmt_bytes}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
  &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt; Configured Remote Capacity:&amp;lt;/th&amp;gt;&amp;lt;td&amp;gt;{ProvidedCapacity|fmt_bytes}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
  &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt; DFS Used:&amp;lt;/th&amp;gt;&amp;lt;td&amp;gt;{Used|fmt_bytes} ({PercentUsed|fmt_percentage})&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
  &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt; Non DFS Used:&amp;lt;/th&amp;gt;&amp;lt;td&amp;gt;{NonDfsUsedSpace|fmt_bytes}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
  &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt; DFS Remaining:&amp;lt;/th&amp;gt;&amp;lt;td&amp;gt;{Free|fmt_bytes} ({PercentRemaining|fmt_percentage})&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
  &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt; Block Pool Used:&amp;lt;/th&amp;gt;&amp;lt;td&amp;gt;{BlockPoolUsedSpace|fmt_bytes} ({PercentBlockPoolUsed|fmt_percentage})&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
  &amp;lt;tr&amp;gt;&amp;lt;th&amp;gt; DataNodes usages% (Min/Median/Max/stdDev): &amp;lt;/th&amp;gt;
	&amp;lt;td&amp;gt;{#NodeUsage.nodeUsage}{min} / {median} / {max} / {stdDev}{/NodeUsage.nodeUsage}&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
{/nn}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;dfshealth.html 파일에서 해당 값을 사용하는 것을 확인했습니다. 그리고 html 파일이 있는 경로에 비슷한 이름으로 dfshealth.js 파일을 발견했습니다. 그래서 dfshealth.js 파일을 확인한 결과 HDFS 정보를 가져오는 출처를 알 수 있어습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;dfshealth.js&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1680427380175&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; $.get(
      '/jmx?qry=Hadoop:service=NameNode,name=NameNodeInfo',
      guard_with_startup_progress(function (resp) {
        var data = workaround(resp.beans[0]);
        ....&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;dfshealth.js에서 JMX 호출을 통해 NameNode의 metric 값을 가져오는 것을 확인할 수 있었습니다.&lt;/span&gt;&lt;/b&gt; 그래서 해당 주소로 제가 사용하는 NameNode에 접근해봤습니다.&amp;nbsp;결과는 원하는 정보를 문제없이 불러올 수 있었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1o2Hx/btr7gSBIk29/gbmx51LusCAlCP76zvkwS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1o2Hx/btr7gSBIk29/gbmx51LusCAlCP76zvkwS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1o2Hx/btr7gSBIk29/gbmx51LusCAlCP76zvkwS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1o2Hx%2Fbtr7gSBIk29%2Fgbmx51LusCAlCP76zvkwS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;852&quot; height=&quot;776&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;776&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;nbsp;위의 Metric에서 현재 HDFS의 전체 용량, 사용량, 사용률, node별 사용 현황 등 여러가지 값들을 받을 수 있습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;NameNodeInfo라는 이름의 Metric 값을 불러왔는데 다른 Metric 값은 없을까하는 궁금증이 생겼습니다. 그래서 위의 주소 값에서 jmx만 남겨두고 확인을 해봤습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;873&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oUbfB/btr7n2Q28oT/fPaKb53jsIENanqdob0j51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oUbfB/btr7n2Q28oT/fPaKb53jsIENanqdob0j51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oUbfB/btr7n2Q28oT/fPaKb53jsIENanqdob0j51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoUbfB%2Fbtr7n2Q28oT%2FfPaKb53jsIENanqdob0j51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;852&quot; height=&quot;873&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;873&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;그 결과 HDFS의 여러 Metric 값들을 모두 확인할 수 있었습니다.&lt;/span&gt;&lt;/b&gt; 만약 웹이나 여러 프로그래밍 코드에서 해당 HDFS 정보를 이용하고 싶다면 JMX Metric 값들을 호출해서 HTTP response로 활용할 수 있을 것 같습니다.&lt;/p&gt;</description>
      <category>Hadoop Ecosystem/Hadoop</category>
      <category>hdfs</category>
      <category>jmx</category>
      <category>metric</category>
      <category>namenode</category>
      <author>Taaewoo</author>
      <guid isPermaLink="true">https://taaewoo.tistory.com/80</guid>
      <comments>https://taaewoo.tistory.com/80#entry80comment</comments>
      <pubDate>Sun, 2 Apr 2023 19:29:28 +0900</pubDate>
    </item>
    <item>
      <title>Riot Data Pipeline 구축하기 #6 - Spark Streaming으로 Kafka Consumer 구현 및 HDFS에 데이터 저장하기</title>
      <link>https://taaewoo.tistory.com/78</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;지난 글에서 Spring을 통해 Match 정보를 Kafka에 전송하는 과정까지 진행했습니다. 이번 글에서는 Kafka에 쌓인 데이터 확인과 Spark Streaming으로 Kafka Consumer를 구현하는 과정을 진행하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Kafka Topic 확인하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Kafka Manager를 이용하면 Kafka 클러스터와 Topic 모니터링을 효율적으로 할 수 있습니다. Kafka 서비스를 위한 docker compose의 Kafka Manager 웹 GUI를 보면 아래와 같습니다. ( Kafka Cluster 등록 과정 필요 )&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;482&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b58DuG/btrYf1ukKTo/7xwVOZf91xrBk56VC53hkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b58DuG/btrYf1ukKTo/7xwVOZf91xrBk56VC53hkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b58DuG/btrYf1ukKTo/7xwVOZf91xrBk56VC53hkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb58DuG%2FbtrYf1ukKTo%2F7xwVOZf91xrBk56VC53hkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;696&quot; height=&quot;400&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;482&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;b&gt;Topic 정보 또한 확인이 가능&lt;/b&gt;합니다. GUI가 없다면 직접 터미널에서 명령어를 통해 확인해야만 합니다. 하지만 Kafka Manager를 통해 쉽게 정보들을 확인할 수 있습니다. Spring에서 &quot;summoner-match&quot;라는 이름의 Topic 데이터가 Kafka Broker에 저장되어 있는 모습을 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;389&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IE7GL/btrYfZDhemH/GHs51JCuFeYJOVZf6Dxoyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IE7GL/btrYfZDhemH/GHs51JCuFeYJOVZf6Dxoyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IE7GL/btrYfZDhemH/GHs51JCuFeYJOVZf6Dxoyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIE7GL%2FbtrYfZDhemH%2FGHs51JCuFeYJOVZf6Dxoyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;896&quot; height=&quot;409&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;389&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Spark Streaming으로 Consumer 구현&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Spark Streaming을 이용하여 Kafka Topic을 가져오는 것은 지난 글들에서 진행했습니다. ( &lt;u&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://taaewoo.tistory.com/32&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Spark] Spark structured streaming으로 Kafka topic 받기 #3 - pyspark로 HDFS에 topic data 저장하기&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;) 이번에도 이와 비슷하게 진행했고, Json 데이터를 다룬다는 점에서 차이가 있었습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Spark를 사용하기 위한 docker-compose.yml 파일은 아래처럼 명시해줍니다. HDFS 또는 Hive와 같은 서비스가 추가적인 서비스가 필요하다면 이어서 추가해주면 됩니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;b&gt;docker-compose.yml&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #800000;&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;'2'&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; services&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; spark-master&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/spark-master:2.4.0-hadoop2.8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;8080:8080&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;7077:7077&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;environment&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;INIT_DAEMON_STEP=setup_spark&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; spark-worker-1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/spark-worker:2.4.0-hadoop2.8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;depends_on&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;spark-master&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;8081:8081&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;environment&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;SPARK_MASTER=spark://spark-master:7077&quot;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; spark-notebook&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/spark-notebook:2.1.0-hadoop2.8-hive&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;container_name&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;spark-notebook&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;9001:9001&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; namenode&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/hadoop-namenode:1.1.0-hadoop2.8-java8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;container_name&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;namenode&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;volumes&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./data/namenode:/hadoop/dfs/name&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;environment&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;CLUSTER_NAME=test&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;50070:50070&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; datanode&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/hadoop-datanode:1.1.0-hadoop2.8-java8&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;depends_on&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;namenode&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;volumes&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./data/datanode:/hadoop/dfs/data&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;-&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;50075:50075&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; hive-server&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/hive:2.3.2-postgresql-metastore&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;volumes&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hive_dir:/root&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;environment&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;HIVE_CORE_CONF_javax_jdo_option_ConnectionURL&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;jdbc:postgresql://hive-metastore/metastore&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;SERVICE_PRECONDITION&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;hive-metastore:9083&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;10000:10000&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;8000:8000&quot;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; hive-metastore&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/hive:2.3.2-postgresql-metastore&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;env_file&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;./hadoop.env&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;olor: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;command&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;/opt/hive/bin/hive --service metastore&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;bcolor: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;environment&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;SERVICE_PRECONDITION&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;namenode:50070 datanode:50075 hive-metastore-postgresql:5432&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ports&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&quot;9083:9083&quot;&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;color: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&amp;nbsp; &amp;nbsp; hive-metastore-postgresql&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;bcolor: #800000; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;bde2020/hive-metastore-postgresql:2.3.0&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Spark에서 Match 데이터를 Kafka로부터 가져와 전처리 후 필요한 정보만 선별하여 HDFS에 저장하고 싶었습니다. 하지만 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;데이터를 사용하기 위한 방법으로, 원본 데이터를 데이터 플랫폼에 저장 후 파싱 후 새로운 테이블로 저장하는 데이터 마트 구축 방식을 이용하고 싶었습니다.&lt;/span&gt;&lt;/b&gt; 그래서 Kafka Topic을 json 데이터 형태로 HDFS에 저장하는 것을 목표로 정했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Spark Streaming으로 Consumer를 구현한 코드와 spark-submit 실행 코드는 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1675500825232&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from pyspark.sql import SparkSession
from pyspark.sql.functions import from_json, col

import json

spark = SparkSession.builder \
    .master(&quot;local&quot;) \
    .appName(&quot;Consume Riot Data&quot;) \
    .getOrCreate()

spark.sparkContext.setLogLevel('ERROR')

json_schema = spark.read.json(&quot;/riot/sample_one_data&quot;).schema


# Read stream
log = spark.readStream.format(&quot;kafka&quot;) \
.option(&quot;kafka.bootstrap.servers&quot;, &quot;host.docker.internal:19096,host.docker.internal:29096,host.docker.internal:39096&quot;) \
.option(&quot;subscribe&quot;, &quot;summoner-match&quot;) \
.option(&quot;startingOffsets&quot;, &quot;earliest&quot;) \
.load()

print(&quot;**ReadStream Kafka topic schema&quot;)
log.printSchema()


parsed_df = log.select(from_json(col(&quot;value&quot;).cast(&quot;string&quot;), json_schema) \
    .alias(&quot;parsed_value&quot;)).select(col(&quot;parsed_value.*&quot;))


query = parsed_df \
.writeStream \
.format(&quot;json&quot;) \
.option(&quot;checkpointLocation&quot;, &quot;/checkpoints/match_raw_data&quot;) \
.option(&quot;path&quot;, &quot;/riot/match_raw_data&quot;) \
.option(&quot;maxRecordsPerFile&quot;, 1) \
.start()

query2 = parsed_df \
    .writeStream \
    .format(&quot;console&quot;) \
    .start()

query.awaitTermination()
query2.awaitTermination()&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1676217629511&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sh /spark/bin/spark-submit --packages org.apache.spark:spark-sql-kafka-0-10_2.11:2.4.0 consume_match_data_store.py&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이때 spark.readStream에서 Kafka 주소에 &quot;host.docker.internal:19096 ... 29096 ... 39096&quot;을 넣어준 이유는 Kafka 클러스터와 Spark 서비스가 실행되는 클러스터는 서&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;로 다른 docker compose이므로 서로의 hostname을 인식할 수 없기 때문&lt;/span&gt;&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Kafka와 Spark의 docker-compose와 서로 통신하는 구조는 아래와 같습니다. Kafka를 docker로 사용할 때 host machine과 통신하는 구체적인 방법은 이전 글을 참고해주시기 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://taaewoo.tistory.com/59&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;[Kafka] Docker로 Kafka 구성 시 Host machine과 통신하기 위한 listener 설정 방법&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;784&quot; data-origin-height=&quot;759&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dyEf8m/btrY8imFK6x/yMfWqiiJgfuEftykVVTKwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dyEf8m/btrY8imFK6x/yMfWqiiJgfuEftykVVTKwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dyEf8m/btrY8imFK6x/yMfWqiiJgfuEftykVVTKwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdyEf8m%2FbtrY8imFK6x%2FyMfWqiiJgfuEftykVVTKwK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;697&quot; height=&quot;675&quot; data-origin-width=&quot;784&quot; data-origin-height=&quot;759&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Match 데이터 HDFS에 저장된 결과&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위의 Spark Streaming을 통한 Consumer 작업이 끝났다면, HDFS 명령어를 통해 데이터가 제대로 저장되었는지 확인합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676220757792&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ hdfs dfs -ls /riot/match_raw_data&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;595&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k7GU8/btrYTgduiw4/c70fNnz3oCtjpTMZKQsZVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k7GU8/btrYTgduiw4/c70fNnz3oCtjpTMZKQsZVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k7GU8/btrYTgduiw4/c70fNnz3oCtjpTMZKQsZVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk7GU8%2FbtrYTgduiw4%2Fc70fNnz3oCtjpTMZKQsZVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1240&quot; height=&quot;595&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;595&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이렇게 저장된 데이터를 Hive 테이블에 적재하는 과정은 다음 글에서 소개하도록 하겠습니다.&lt;/p&gt;</description>
      <category>BigData Engineering/Riot Data Pipeline</category>
      <category>Data Pipeline</category>
      <category>docker compose</category>
      <category>kafka</category>
      <category>Riot</category>
      <category>spark</category>
      <category>spark streaming</category>
      <author>Taaewoo</author>
      <guid isPermaLink="true">https://taaewoo.tistory.com/78</guid>
      <comments>https://taaewoo.tistory.com/78#entry78comment</comments>
      <pubDate>Mon, 13 Feb 2023 02:02:18 +0900</pubDate>
    </item>
    <item>
      <title>[Hive] Compile 상세 과정 #2 - Optimization 종류와 소스 코드 분석</title>
      <link>https://taaewoo.tistory.com/77</link>
      <description>&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이전 글에 이어서 Hive의 Compile 상세 과정 중 Optimization의 여러 종류와 Compile 과정의 소스 코드를 분석하도록 하겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Hive Optimization 종류&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Hive는 쿼리를 최종적인 Task Tree로 만들기까지의 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Compile 과정에서 여러 종류의 Optimization을 수행합니다&lt;/b&gt;&lt;/span&gt;. 3가지 종류의 Optimization에 대해서 소개하도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;CBO (Cost-Based Optimization)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Semantic Analyzer가 AST를 OP Tree로 만드는 과정에서의 Optimization.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 참고 링크 : &lt;a href=&quot;https://cwiki.apache.org/confluence/display/Hive/Cost-based+optimization+in+Hive&quot;&gt;https://cwiki.apache.org/confluence/display/Hive/Cost-based+optimization+in+Hive&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1671990979062&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Cost-based optimization in Hive - Apache Hive - Apache Software Foundation&quot; data-og-description=&quot;Abstract Apache Hadoop is a framework for the distributed processing of large data sets using clusters of computers typically composed of commodity hardware. Over last few years Apache Hadoop has become the de facto platform for distributed data processing&quot; data-og-host=&quot;cwiki.apache.org&quot; data-og-source-url=&quot;https://cwiki.apache.org/confluence/display/Hive/Cost-based+optimization+in+Hive&quot; data-og-url=&quot;https://cwiki.apache.org/confluence/display/Hive/Cost-based+optimization+in+Hive&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/wLZ4A/hyQ1ksA4HK/ZeDTFqs0qMiCTMbPoQ1iok/img.jpg?width=651&amp;amp;height=594&amp;amp;face=0_0_651_594&quot;&gt;&lt;a href=&quot;https://cwiki.apache.org/confluence/display/Hive/Cost-based+optimization+in+Hive&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://cwiki.apache.org/confluence/display/Hive/Cost-based+optimization+in+Hive&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/wLZ4A/hyQ1ksA4HK/ZeDTFqs0qMiCTMbPoQ1iok/img.jpg?width=651&amp;amp;height=594&amp;amp;face=0_0_651_594');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Cost-based optimization in Hive - Apache Hive - Apache Software Foundation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Abstract Apache Hadoop is a framework for the distributed processing of large data sets using clusters of computers typically composed of commodity hardware. Over last few years Apache Hadoop has become the de facto platform for distributed data processing&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;cwiki.apache.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Apache Calcite를 이용하여 쿼리 구문을 Cost-Based Optimization하고 OP Tree를 생성합니다. 이때 Optimization은 뒤에서 나올 Logical Plan, Task Plan을 Optimization 하는 것과는 별개인 점을 참고 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Cost-Based Optimization 특징&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Join의 순서를 어떻게 정할지?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 주어진 Join에 대해 어떤 알고리즘을 사용할지?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Operator fail에 대하여 intermediate 결과를 계속 유지할지 또는 다시 계산할지?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 병렬 작업의 정도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Semi Join&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;Apache Calcite?&lt;/b&gt;&lt;br /&gt;- SQL parsing, 쿼리 planning 등의 기능을 가지고 있는 오픈 소스 framework.&lt;br /&gt;- 적용하려는 SQL의 데이터나 metadata를 자체적으로 따로 저장하지 않음.&lt;br /&gt;- 그래서 외부 Metadata 또는 데이터를 plugin 방식으로 사용함.&lt;br /&gt;&amp;nbsp;( Hive에서 사용 시, Metastore가 이용됨. )&lt;br /&gt;&lt;u&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://calcite.apache.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://calcite.apache.org/&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Logical Optimizaion&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Logical Plan으로써 만들어진 OP Tree를 Optimization 수행 ( 실제 파일을 읽는 단계 X )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Logical Optimization 예시&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Predicate Pushdown : Table 전체 row를 scan 후 filter 하는 것이 아니라 filter 후 scan.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Projection Pruning : Select 된 column에 대해서만 pruning.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- (Select - Select) 또는 (Filter-Filter) 구조를 하나의 Operator로 병합.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;....&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Physical Optimization&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Physical Plan으로써 만들어진 Task Tree를 Optimization 수행 ( 실제 파일을 읽는 단계 )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Physical Optimization 예시&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Partition Pruning.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Limit 절 사용 시, 일부 파일만 scan.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Simple fetch 쿼리에 대해서는, MR 작업 없이 수행 ( hive.fetch.task.conversion )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;....&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Compile 과정 소스 코드 분석&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Hive가 Compile을 하면서 쿼리가 변환되는 과정에 대해서 소스 코드와 함께 상세하게 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;( 아래 소스 코드들은 모두 Hive 2.3.2 버전입니다. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;0. Hive 쿼리&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1672069964755&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;select * from test.tbl_1
where par=par_2
limit 7;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;1. Hive 쿼리 -&amp;gt; AST&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1304&quot; data-origin-height=&quot;414&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwLBmL/btrR2rzkxCO/zrrruw8Ylcqd3MDtaiwuB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwLBmL/btrR2rzkxCO/zrrruw8Ylcqd3MDtaiwuB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwLBmL/btrR2rzkxCO/zrrruw8Ylcqd3MDtaiwuB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwLBmL%2FbtrR2rzkxCO%2Fzrrruw8Ylcqd3MDtaiwuB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;127&quot; data-origin-width=&quot;1304&quot; data-origin-height=&quot;414&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;Driver.java&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// compileInternal(String command, boolean deferClose) - Line:1317&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ret = &lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;compile&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(command, &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, deferClose);&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;...&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// compile(String command, boolean resetTaskIds, boolean deferClose) - Line:468&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #267f99;&quot;&gt;ASTNode&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;tree&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;ParseUtils&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;parse&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(command, ctx);&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이전 글에서 언급한 것처럼 아키텍쳐 상으로는 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Compiler라는 모듈이 존재&lt;/span&gt;&lt;/b&gt;하는 것처럼 보였지만, Line 1317 과 같이 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;실제 소스 코드에서는 Driver에서 compile() 메소드를 호출&lt;/span&gt;&lt;/b&gt;하는 것에 불과했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;그리고 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;compile() 메소드에서 ParseUtils를 이용해 Hive 쿼리를 AST로 변환&lt;/span&gt;&lt;/b&gt;하는 것을 확인할 수 있고 결과물인 &lt;b&gt;tree 변수는 아래처럼 쿼리가 각 토큰별로 트리 형태&lt;/b&gt;를 이루고 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1031&quot; data-origin-height=&quot;526&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cp1Lg1/btrUJir4IQx/81ti7S7iG1UN4TkCIehs11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cp1Lg1/btrUJir4IQx/81ti7S7iG1UN4TkCIehs11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cp1Lg1/btrUJir4IQx/81ti7S7iG1UN4TkCIehs11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcp1Lg1%2FbtrUJir4IQx%2F81ti7S7iG1UN4TkCIehs11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1031&quot; height=&quot;526&quot; data-origin-width=&quot;1031&quot; data-origin-height=&quot;526&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;2. AST&amp;nbsp;-&amp;gt; QB&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdGsEI/btrUEv6fMWV/QK6byMgazLbRh4b4lmfJsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdGsEI/btrUEv6fMWV/QK6byMgazLbRh4b4lmfJsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdGsEI/btrUEv6fMWV/QK6byMgazLbRh4b4lmfJsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdGsEI%2FbtrUEv6fMWV%2FQK6byMgazLbRh4b4lmfJsK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;543&quot; height=&quot;219&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;SemanticAnalyzerFactory.java&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// get(QueryState queryState, ASTNode tree) - Line:317&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// hive.cbo.enabled 옵션 값에 따른 SemanticAnalyzer 객체 생성&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// True : CalcitePlanner&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// False : SemanticAnalyzer&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #267f99;&quot;&gt;SemanticAnalyzer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;semAnalyzer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #267f99;&quot;&gt;HiveConf&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; .&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;getBoolVar&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;queryState&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;getConf&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;HiveConf&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;ConfVars&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;HIVE_CBO_ENABLED&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;?&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;CalcitePlanner&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(queryState) &lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;SemanticAnalyzer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(queryState);&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;AST를 QB로 변환하기에 앞서 &lt;b&gt;&lt;i&gt;Driver&lt;/i&gt;&lt;/b&gt;에서 &lt;b&gt;SemanticAnalyzer의 객체를 생성&lt;/b&gt;합니다. 그래서 SemanticAnalyzerFactory의 코드를 확인해보면 hive.cbo.enabled 옵션 값에 따라 CalcitePlanner 또는 SemanticAnalyzer로 할당하는 것을 확인할 수 있습니다. 즉, &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;CalcitePlanner와 SemanticAnalyzer는 서로 상속 관계인 것을 확인&lt;/span&gt;&lt;/b&gt;할 수 있었습니다.&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;public class CalcitePlanner extends SemanticAnalyzer&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;이후 다시 Driver에서 SemanticAnalyzer의 메소드를 호출합니다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;Driver.java&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// compile(String command, boolean resetTaskIds, boolean deferClose) - Line:506&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// Semantic Analyzer 함수 사용&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #001080;&quot;&gt;sem&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;analyze&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(tree, ctx);&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;SenticAnalyzer의 메소드를 따라서 내부로 들어가면 doPhase1() 이라는 메소드에서 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;AST의 각 토큰 값을 DFS 탐색으로 순회하면서 QB 객체에 정보를 저장&lt;/span&gt;&lt;/b&gt;합니다. ( CalcitePlanner에 의해 QB가 생성되는 과정은 생략하겠습니다. )&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;SemanticAnalyzer.java&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// doPhase1(ASTNode ast, QB qb, Phase1Ctx ctx_1, PlannerContext plannerCtx) - Line:1428&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// AST의 각 토큰 값 DFS 순회로 QB에 정보 저장&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;skipRecursion = &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;switch&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;ast&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;getToken&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;getType&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;()) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;&amp;nbsp; &amp;nbsp; case&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;HiveParser&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;TOK_SELECTDI&lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; qb&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;countSelDi&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // fall through&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;&amp;nbsp; &amp;nbsp; case&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;HiveParser&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;TOK_SELECT&lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; qb&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;countSel&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; qbp&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;setSelExprForClause&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;ctx_1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;dest&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, ast);&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;...&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (!skipRecursion) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;nbsp; &amp;nbsp; // Iterate over the rest of the children&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #267f99;&quot;&gt;&amp;nbsp; &amp;nbsp; int&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;child_count&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;ast&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;getChildCount&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;&amp;nbsp; &amp;nbsp; for&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #267f99;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;child_pos&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #098658;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;; child_pos &amp;lt; child_count &amp;amp;&amp;amp; phase1Result; ++child_pos) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Recurse&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; phase1Result = phase1Result &amp;amp;&amp;amp; &lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;doPhase1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (ASTNode)&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;ast&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;getChild&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(child_pos), qb, ctx_1, plannerCtx);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;...&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;작업이 다 수행되면 아래와 같이 QB에 QBParseInfo와 QBMetaData에 필요한 정보가 저장됩니다.&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1131&quot; data-origin-height=&quot;785&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p7dTW/btrUMPilR9y/5kRmsWKm3flit7RXpIN1ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p7dTW/btrUMPilR9y/5kRmsWKm3flit7RXpIN1ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p7dTW/btrUMPilR9y/5kRmsWKm3flit7RXpIN1ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp7dTW%2FbtrUMPilR9y%2F5kRmsWKm3flit7RXpIN1ik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1131&quot; height=&quot;785&quot; data-origin-width=&quot;1131&quot; data-origin-height=&quot;785&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;3. QB&amp;nbsp;-&amp;gt; OP Tree (Optimized)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2UMfx/btrUHSAIjE1/ThTFdK9OzuLgNFmXHkfT41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2UMfx/btrUHSAIjE1/ThTFdK9OzuLgNFmXHkfT41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2UMfx/btrUHSAIjE1/ThTFdK9OzuLgNFmXHkfT41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2UMfx%2FbtrUHSAIjE1%2FThTFdK9OzuLgNFmXHkfT41%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;528&quot; height=&quot;175&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;SemanticAnalyzer.java&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// analyzeInternal(ASTNode ast, PlannerContext plannerCtx) - Line:11138&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #267f99;&quot;&gt;Operator&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;sinkOp&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;genOPTree&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(ast, plannerCtx);&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;다시 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;SemanticAnalyzer에서 OP Tree를 생성하는 메소드를 호출&lt;/span&gt;&lt;/b&gt;합니다. 이때 CBO 옵션이 True라면 CalcitePlanner의 Override 된 genOPTree() 메소드가 호출되고, False라면 그대로 SemanticAnalyzer의 genOPTree() 메소드가 호출됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;883&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2gPbD/btrUL8vI8hA/bTyNRCd0NbEZTLo1MkKLN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2gPbD/btrUL8vI8hA/bTyNRCd0NbEZTLo1MkKLN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2gPbD/btrUL8vI8hA/bTyNRCd0NbEZTLo1MkKLN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2gPbD%2FbtrUL8vI8hA%2FbTyNRCd0NbEZTLo1MkKLN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;883&quot; height=&quot;592&quot; data-origin-width=&quot;883&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이후에는 &amp;nbsp;SemanticAnalyzer에서 Optimizer 객체를 생성 후 OP Tree를 최적화합니다. 그 결과는 pCtx 변수에 저장되고 내부 변수들을 확인해보면 최적화된 OP Tree를 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;134&quot; data-origin-height=&quot;185&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvQez5/btrUE5tOFPD/ESe6ZaHO2QlbgzhF1Vk5RK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvQez5/btrUE5tOFPD/ESe6ZaHO2QlbgzhF1Vk5RK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvQez5/btrUE5tOFPD/ESe6ZaHO2QlbgzhF1Vk5RK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvQez5%2FbtrUE5tOFPD%2FESe6ZaHO2QlbgzhF1Vk5RK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;154&quot; height=&quot;213&quot; data-origin-width=&quot;134&quot; data-origin-height=&quot;185&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;SemanticAnalyzer.java&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// analyzeInternal(ASTNode ast, PlannerContext plannerCtx) - Line:11244&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #267f99;&quot;&gt;Optimizer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;optm&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;Optimizer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #001080;&quot;&gt;optm&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;setPctx&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(pCtx);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #001080;&quot;&gt;optm&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;initialize&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(conf);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;pCtx = &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;optm&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;optimize&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;923&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3jaRt/btrUInmSHtg/0jCVFU5kxIKbScKUVhkRWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3jaRt/btrUInmSHtg/0jCVFU5kxIKbScKUVhkRWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3jaRt/btrUInmSHtg/0jCVFU5kxIKbScKUVhkRWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3jaRt%2FbtrUInmSHtg%2F0jCVFU5kxIKbScKUVhkRWk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1003&quot; height=&quot;923&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;923&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;5. OP Tree (&lt;b&gt;Optimized) -&amp;gt; Task Tree (Optimized)&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;389&quot; data-origin-height=&quot;216&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caGuyp/btrUNrn6oH1/yOrWXNTgglZIqKKmLSd0VK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caGuyp/btrUNrn6oH1/yOrWXNTgglZIqKKmLSd0VK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caGuyp/btrUNrn6oH1/yOrWXNTgglZIqKKmLSd0VK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaGuyp%2FbtrUNrn6oH1%2FyOrWXNTgglZIqKKmLSd0VK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;432&quot; height=&quot;240&quot; data-origin-width=&quot;389&quot; data-origin-height=&quot;216&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;TezCompilerFactory.java&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// TaskCompiler getCompiler(HiveConf conf, ParseContext parseContext) - Line:39&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// Execution Engine에 따른 Compiler 객체 생성&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;HiveConf&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;getVar&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(conf, &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;HiveConf&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;ConfVars&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;HIVE_EXECUTION_ENGINE&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;equals&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;tez&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;&amp;nbsp; &amp;nbsp; return&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;TezCompiler&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;HiveConf&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;getVar&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(conf, &lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;HiveConf&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;ConfVars&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #001080;&quot;&gt;HIVE_EXECUTION_ENGINE&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;equals&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;spark&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;&amp;nbsp; &amp;nbsp; return&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;SparkCompiler&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; } &lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;&amp;nbsp; &amp;nbsp; return&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #af00db;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;MapReduceCompiler&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;();&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; }&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;TaskCompiler는 Hive의 Execution Engine 종류에 따라 객체가 생성됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;SemanticAnalyzer&lt;/span&gt;&lt;/b&gt;.java&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// analyzeInternal(ASTNode ast, PlannerContext plannerCtx) - Line:11273&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #001080;&quot;&gt;compiler&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;compile&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(pCtx, rootTasks, inputs, outputs);&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;SemanticAnalyzer에서 TaskCompiler를 이용하여 Task Tree를 생성합니다. 이때 TaskCompiler의 compile 메소드는 Task Tree 생성 및 최적화 과정을 모두 포함합니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;TaskCompiler&lt;/span&gt;&lt;/b&gt;.java&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// compile(final ParseContext pCtx, final List&amp;lt;Task&amp;lt;? extends Serializable&amp;gt;&amp;gt; rootTasks,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// final HashSet&amp;lt;ReadEntity&amp;gt; inputs, final HashSet&amp;lt;WriteEntity&amp;gt; outputs) - Line:279&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;generateTaskTree&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(rootTasks, pCtx, mvTask, inputs, outputs);&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// compile(final ParseContext pCtx, final List&amp;lt;Task&amp;lt;? extends Serializable&amp;gt;&amp;gt; rootTasks,&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #008000;&quot;&gt;// final HashSet&amp;lt;ReadEntity&amp;gt; inputs, final HashSet&amp;lt;WriteEntity&amp;gt; outputs) - Line:292&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #795e26;&quot;&gt;optimizeTaskPlan&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(rootTasks, pCtx, ctx);&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;최적화까지 모두 수행되면 아래와 같이 rootTasks와 fetchTask에 Task들이 부여됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;285&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6lRvo/btrUNWhazrh/wGFlcPBF2KlzbHfkqJb0Vk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6lRvo/btrUNWhazrh/wGFlcPBF2KlzbHfkqJb0Vk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6lRvo/btrUNWhazrh/wGFlcPBF2KlzbHfkqJb0Vk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6lRvo%2FbtrUNWhazrh%2FwGFlcPBF2KlzbHfkqJb0Vk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;350&quot; height=&quot;285&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;285&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위의 과정으로 Compile 과정은 모두 종료가 됩니다. 마지막으로 Driver는 Execution Engine에 Task들을 전달하면서 YARN을 통해 어플리케이션이 실행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Hive 쿼리 실행 Log 내용 이해하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이제는 위의 내용들을 기반으로 Hive 쿼리를 실행할 때 출력되는 Log를 이해할 수 있을 것입니다. ( Debug 모드 출력 )&lt;/p&gt;
&lt;div style=&quot;width: 100%; overflow: auto; font-size: 0.85rem;&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 207.094%; height: 971px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;Debug_Console&lt;/span&gt;&lt;/b&gt;.log&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;// Hive 쿼리&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&amp;gt; select * from &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;test.tbl_1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; where par=&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;par_2&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; limit &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;// Parser : Hive 쿼리 -&amp;gt; AST&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:44&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #0451a5;&quot;&gt;DEBUG&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;parse.ParseDriver&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Parsing command: select * from &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;test.tbl_1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; where par=&lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;par_2&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; limit &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;7&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:44&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #0451a5;&quot;&gt;DEBUG&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;parse.ParseDriver&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Parse Completed&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;// Semantic Analyzer ( Calcite Planner )&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:45&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #098658;&quot;&gt;INFO&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;parse.CalcitePlanner&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Starting Semantic Analysis&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:47&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #0451a5;&quot;&gt;DEBUG&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;parse.CalcitePlanner&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: CBO Planning details:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:47&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #0451a5;&quot;&gt;DEBUG&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;parse.CalcitePlanner&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Original Plan:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HiveSortLimit(offset=[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;], fetch=[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;])&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; HiveProject(col_1=[$&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;], col_2=[$&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;], col_3=[$&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;], par=[$&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;])&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; HiveFilter(condition=[=($&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, _UTF-16LE'par_2')])&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; HiveTableScan(table=[[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;test.tbl_1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]], table:alias=[tbl_1])&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:47&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #0451a5;&quot;&gt;DEBUG&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;parse.CalcitePlanner&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Plan After Join Reordering:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;HiveSortLimit(fetch=[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]): rowcount = &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, cumulative cost = {&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; rows, &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; cpu, &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; io}, id = &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;121&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; HiveProject(col_1=[$&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;], col_2=[$&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;], col_3=[$&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;], par=[CAST(_UTF-16LE'par_2'):VARCHAR(&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2147483647&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;) CHARACTER SET &lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;UTF-16LE&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; COLLATE &lt;/span&gt;&lt;span style=&quot;color: #a31515;&quot;&gt;&quot;ISO-8859-1$en_US$primary&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]): rowcount = &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, cumulative cost = {&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; rows, &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; cpu, &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; io}, id = &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;119&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; HiveFilter(condition=[=($&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, _UTF-16LE'par_2')]): rowcount = &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, cumulative cost = {&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; rows, &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; cpu, &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; io}, id = &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;117&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt; HiveTableScan(table=[[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;test.tbl_1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]], table:alias=[tbl_1]): rowcount = &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, cumulative cost = {&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;}, id = &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;67&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:47&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #098658;&quot;&gt;INFO&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;parse.CalcitePlanner&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: CBO Succeeded; optimized logical plan.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;// OP Tree&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:47&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #0451a5;&quot;&gt;DEBUG&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;parse.CalcitePlanner&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Before logical optimization&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TS[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]-FIL[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]-SEL[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]-LIM[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]-FS[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;// OP Tree (Optimized)&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:48&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #0451a5;&quot;&gt;DEBUG&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;parse.CalcitePlanner&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: After logical optimization&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TS[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]-SEL[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]-LIM[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]-LIST_SINK[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:48&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #098658;&quot;&gt;INFO&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;ql.Driver&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Semantic Analysis Completed&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;// Task Tree&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:48&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #098658;&quot;&gt;INFO&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;exec.TableScanOperator&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Initializing operator TS[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:48&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #098658;&quot;&gt;INFO&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;exec.SelectOperator&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Initializing operator SEL[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:48&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #098658;&quot;&gt;INFO&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;exec.LimitOperator&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Initializing operator LIM[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:48&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #098658;&quot;&gt;INFO&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;exec.ListSinkOperator&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Initializing operator LIST_SINK[&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;]&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:48&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #0451a5;&quot;&gt;DEBUG&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;exec.ListSinkOperator&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Initialization Done &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; LIST_SINK done is reset.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:48&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #0451a5;&quot;&gt;DEBUG&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;exec.LimitOperator&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Initialization Done &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; LIM done is reset.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:48&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #0451a5;&quot;&gt;DEBUG&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;exec.SelectOperator&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Initialization Done &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; SEL done is reset.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #008000;&quot;&gt;08:22:48&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3852e623-31d5-427e-908a-5b621396c939&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; main]: &lt;/span&gt;&lt;span style=&quot;color: #0451a5;&quot;&gt;DEBUG&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;exec.TableScanOperator&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: Initialization Done &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; TS done is reset.&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;// Result&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; banana &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; par_2&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; apple &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;34&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; par_2&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; melon &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;156&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; par_2&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; lemon &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;23&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; par_2&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; tomato &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;11&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; par_2&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; banana &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;41&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; par_2&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; apple &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;52&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; par_2&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Time taken: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;81&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; seconds, Fetched: &lt;/span&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; row(s)&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Hadoop Ecosystem/Hive</category>
      <category>AST</category>
      <category>compile</category>
      <category>Hive</category>
      <category>Hive 쿼리 compile</category>
      <category>OP Tree</category>
      <category>QB</category>
      <category>Task Tree</category>
      <author>Taaewoo</author>
      <guid isPermaLink="true">https://taaewoo.tistory.com/77</guid>
      <comments>https://taaewoo.tistory.com/77#entry77comment</comments>
      <pubDate>Tue, 27 Dec 2022 17:39:31 +0900</pubDate>
    </item>
    <item>
      <title>[Hive] Compile 상세 과정 #1 - 쿼리 변화 과정과 형태</title>
      <link>https://taaewoo.tistory.com/75</link>
      <description>&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Hive를 이용하면서 Client로부터 제출된 쿼리가 어떻게 MR Job으로까지 변환이 될까라는 궁금증이 항상 있었습니다. 그래서 내부적인 Compile 과정에 대해서 공부를 하게 되었고, 소스 코드를 직접 분석해 봤습니다. 이전에 작성한 &lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://taaewoo.tistory.com/64&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[Hive] Hive 아키텍처와 HiveServer2 &amp;amp; Hive Metastore&lt;/a&gt;&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&amp;nbsp; 글을 먼저 읽으면 본 게시글을 이해하는데 도움이 될 겁니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Hive Architecture Review&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LyJQD/btrRXnXvtN3/aptb0hoCmau1xqsZKCFR7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LyJQD/btrRXnXvtN3/aptb0hoCmau1xqsZKCFR7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LyJQD/btrRXnXvtN3/aptb0hoCmau1xqsZKCFR7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLyJQD%2FbtrRXnXvtN3%2Faptb0hoCmau1xqsZKCFR7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;684&quot; height=&quot;871&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1630&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 주요 프로세스로 HiveServer2, Metastore 존재&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Driver가 중심에서 컴파일 과정, Task 전달 등 수행.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Hive 쿼리의 변화 과정을 알기 위해선 &lt;b&gt;위 그림의 Compiler 과정을 알아야함.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Hive 쿼리 처리 과정&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d800cU/btrRYxkL7GE/YjHZpGDALwMCkCiem3bA7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d800cU/btrRYxkL7GE/YjHZpGDALwMCkCiem3bA7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d800cU/btrRYxkL7GE/YjHZpGDALwMCkCiem3bA7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd800cU%2FbtrRYxkL7GE%2FYjHZpGDALwMCkCiem3bA7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;560&quot; height=&quot;73&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;176&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Hive 쿼리가 최종적으로 Map Reduce Job이 된다는 것은 잘 알고 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;하지만 대부분의 에러 발생은 중간 과정에서 발생.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 위의 과정을 모른다면 에러의 원인을 파악하기 힘듦.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1528&quot; data-origin-height=&quot;654&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W4piK/btrR2H9GBaq/Myip3WS6omeQHCB7Qb4s10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W4piK/btrR2H9GBaq/Myip3WS6omeQHCB7Qb4s10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W4piK/btrR2H9GBaq/Myip3WS6omeQHCB7Qb4s10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW4piK%2FbtrR2H9GBaq%2FMyip3WS6omeQHCB7Qb4s10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;561&quot; height=&quot;240&quot; data-origin-width=&quot;1528&quot; data-origin-height=&quot;654&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Architecture 그림에서 Compiler와 Driver를 모듈로써 따로 분리를 시키면 위와 같습니다. 하지만 제가 실제로 알아본 Hive 쿼리의 Compile 과정은 조금 달랐습니다. 아래의 그림을 통해 설명하겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2174&quot; data-origin-height=&quot;2410&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzFHDK/btrR5hItVxs/2iU006AJkNHDwtpKI8eXkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzFHDK/btrR5hItVxs/2iU006AJkNHDwtpKI8eXkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzFHDK/btrR5hItVxs/2iU006AJkNHDwtpKI8eXkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzFHDK%2FbtrR5hItVxs%2F2iU006AJkNHDwtpKI8eXkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;764&quot; height=&quot;847&quot; data-origin-width=&quot;2174&quot; data-origin-height=&quot;2410&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Hive Architecture에서 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Compiler 모듈이 존재했던 것과 달리&lt;/span&gt;&lt;/b&gt; 실제 과정에서는 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;쿼리의 변화 과정에 필요한 각 모듈들이&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;모두 Driver에서 호출&lt;/span&gt;&lt;/b&gt;되어&amp;nbsp;&lt;/span&gt;사용되었습니다. 위 그림에서 확인할 수 있는 Hive 쿼리의 변화 과정은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;Hive 쿼리 &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- &lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;AST&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- &lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;QB&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- &lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;OP Tree&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- &lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Task Tree&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Hive 쿼리의 변환 형태&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Hive가 변환되면서 거치게 되는 각각의 형태에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;&lt;i&gt;AST&amp;nbsp;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;Abstract Syntax Tree,&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;일반적인 프로그래밍 Compile 과정에서 쓰이는 개념으로 추상화된 트리를 뜻합니다. 코드 또는 쿼리의 각 구문을 트리 형태로 분리시킨 형태입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ucZwQ/btrUxpYHsPI/C70U1AkYJY0HU6m5GCv1rK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ucZwQ/btrUxpYHsPI/C70U1AkYJY0HU6m5GCv1rK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ucZwQ/btrUxpYHsPI/C70U1AkYJY0HU6m5GCv1rK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FucZwQ%2FbtrUxpYHsPI%2FC70U1AkYJY0HU6m5GCv1rK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;694&quot; height=&quot;521&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;694&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;&lt;i&gt;QB&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;Query Block,&lt;/b&gt;&lt;span&gt; 쿼리 구조에 대한 정보를 담습니다. 보통 Sub 쿼리가 존재하는 쿼리에서 여러 구조의 QB 정보가 생깁니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;121&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOMNyJ/btrUukqsrvH/xz38Lm3PicpuRlwfnO6BN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOMNyJ/btrUukqsrvH/xz38Lm3PicpuRlwfnO6BN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOMNyJ/btrUukqsrvH/xz38Lm3PicpuRlwfnO6BN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOMNyJ%2FbtrUukqsrvH%2Fxz38Lm3PicpuRlwfnO6BN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;121&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;121&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Hive에서 사용하는 QB의 경우 두 가지 종류의 데이터가 담깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 1) MetaData&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -&amp;gt; 테이블에 대한 Metadata&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 2) ParseInfo&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -&amp;gt; QB에 대한 parsing 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;&lt;i&gt;OP Tree&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;Operator Tree,&lt;/b&gt;&lt;span&gt;&lt;span&gt; Logical Plan으로써 Operator가 Tree 구조로 생성됨.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 17px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 17px;&quot;&gt;&lt;b&gt;Operator 예시&lt;/b&gt;&lt;br /&gt;- TS : Table Scan Operator&lt;br /&gt;- GBY : Group By Operator&lt;br /&gt;- RS : Reduce Sink Operator&lt;br /&gt;- SEL : Select Operator&lt;br /&gt;- FS : File Sink Operator&lt;br /&gt;- FIL : Filter Operator&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Logical Plan은 Hive를 debug 모드로 실행했을 때 Log에서 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1884&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sAEMq/btrUxoZTa2U/mKij3ZhgBQooCf8pYl1NI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sAEMq/btrUxoZTa2U/mKij3ZhgBQooCf8pYl1NI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sAEMq/btrUxoZTa2U/mKij3ZhgBQooCf8pYl1NI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsAEMq%2FbtrUxoZTa2U%2FmKij3ZhgBQooCf8pYl1NI1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;67&quot; data-origin-width=&quot;1884&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;&lt;i&gt;Task Tree&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;Task Tree,&lt;/b&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Logical Plan이 최종적으로 Execution engine에서 수행될 Physical Plan으로 변환된 상태.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 17px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Task 예시&lt;/b&gt;&lt;br /&gt;- Fetch Task : [Stage-0 : FETCH]&lt;br /&gt;- Root Task : [Stage-1 : MAPRED]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;explain 문을 사용하여 쿼리의 plan을 확인할 때 Task Tree 구조를 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1362&quot; data-origin-height=&quot;662&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bp3ZrJ/btrUuqYubxl/XlX9FkN9UHQrOxrBwAF7k0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bp3ZrJ/btrUuqYubxl/XlX9FkN9UHQrOxrBwAF7k0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bp3ZrJ/btrUuqYubxl/XlX9FkN9UHQrOxrBwAF7k0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbp3ZrJ%2FbtrUuqYubxl%2FXlX9FkN9UHQrOxrBwAF7k0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;611&quot; height=&quot;297&quot; data-origin-width=&quot;1362&quot; data-origin-height=&quot;662&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Hadoop Ecosystem/Hive</category>
      <category>AST</category>
      <category>compile</category>
      <category>Hive</category>
      <category>Hive 쿼리 처리 과정</category>
      <category>OP Tree</category>
      <category>QB</category>
      <category>Task Tree</category>
      <author>Taaewoo</author>
      <guid isPermaLink="true">https://taaewoo.tistory.com/75</guid>
      <comments>https://taaewoo.tistory.com/75#entry75comment</comments>
      <pubDate>Sun, 25 Dec 2022 00:59:59 +0900</pubDate>
    </item>
    <item>
      <title>[Hive] Complex Json 데이터 테이블 생성하기 (Json SerDe)</title>
      <link>https://taaewoo.tistory.com/76</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Json 데이터를 사용하다보면 Json의 스키마 자체가 상당히 복잡하고 거대한 경우가 있습니다. 이번 글에서는 complex Json 데이터를 이용해 Hive 테이블을 생성하는 방법에 대해 소개하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Json 데이터로 Hive 테이블 만들기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Json 데이터로 Hive 테이블을 만드는 방법은 여러가지가 있겠지만 이번 글에서는 Json SerDe를 이용한 방법을 소개할 예정입니다. 우선 Json SerDe를 위한 jar 파일부터 아래 링크에서 다운받도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;u&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://jar-download.com/maven-repository-class-search.php?search_box=org.openx.data.jsonserde.JsonSerDe&quot;&gt;https://jar-download.com/maven-repository-class-search.php?search_box=org.openx.data.jsonserde.JsonSerDe&lt;/a&gt;&amp;nbsp;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670864503936&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Download dependencies for java class org.openx.data.jsonserde.JsonSerDe&quot; data-og-description=&quot;io.starburst.openx.data json-serde 1.3.9-e.10 compile group: 'io.starburst.openx.data', name: 'json-serde', version: '1.3.9-e.10' //Thanks for using https://jar-download.com libraryDependencies += &amp;quot;io.starburst.openx.data&amp;quot; % &amp;quot;json-serde&amp;quot; % &amp;quot;1.3.9-e.10&amp;quot; //T&quot; data-og-host=&quot;jar-download.com&quot; data-og-source-url=&quot;https://jar-download.com/maven-repository-class-search.php?search_box=org.openx.data.jsonserde.JsonSerDe&quot; data-og-url=&quot;https://jar-download.com/maven-repository-class-search.php?search_box=org.openx.data.jsonserde.JsonSerDe&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://jar-download.com/maven-repository-class-search.php?search_box=org.openx.data.jsonserde.JsonSerDe&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jar-download.com/maven-repository-class-search.php?search_box=org.openx.data.jsonserde.JsonSerDe&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Download dependencies for java class org.openx.data.jsonserde.JsonSerDe&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;io.starburst.openx.data json-serde 1.3.9-e.10 compile group: 'io.starburst.openx.data', name: 'json-serde', version: '1.3.9-e.10' //Thanks for using https://jar-download.com libraryDependencies += &quot;io.starburst.openx.data&quot; % &quot;json-serde&quot; % &quot;1.3.9-e.10&quot; //T&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jar-download.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위의 링크에서 1.3.7.3 버전을 다운 받고 zip 파일을 풀어주면 &lt;b&gt;&quot;json-1.3.7.3.jar&quot;, &quot;json-serde-cdh5-shim-1.3.7.3.jar&quot;, &quot;json-serde-1.3.7.3.jar&quot;&lt;/b&gt; 파일들이 나오게 됩니다. 이 파일들을 Hive의 lib 디렉토리에 넣어줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;저의 경우 Docker를 이용해서 Hive를 사용했고 &quot;$HIVE_HOME/lib&quot; 경로에 넣어줬습니다. ( $HIVE_HOME : /opt/hive ) HIVE_HOME은 사용하는 플랫폼마다 다를 수 있으니 참고바랍니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;간단한 예제를 보여드리겠습니다. 아래처럼 Json 파일 생성 후 HDFS 경로에 넣어줍니다. &lt;b&gt;( 게시글에서는 이렇게 줄바꿈을 넣었지만, 개행문자는 뒤에서 Hive 테이블을 select 하는 과정에서 에러가 납니다. 꼭 줄바꿈을 모두 없애고 저장해주세요. )&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;b&gt;simple_schema.json&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &quot;key1&quot; : {&quot;sub_key1&quot; : &quot;sub_value1&quot;, &quot;sub_key2&quot; : &quot;sub_value2&quot;},&lt;br /&gt;&amp;nbsp; &amp;nbsp; &quot;key2&quot; : 1357,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &quot;key3&quot; : [&quot;list_value1&quot;, &quot;list_value2&quot;, &quot;list_value3&quot;]&lt;br /&gt;}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;{&quot;key1&quot; : {&quot;sub_key1&quot; : &quot;sub_value1&quot;, &quot;sub_key2&quot; : &quot;sub_value2&quot;},&quot;key2&quot; : 1357,&quot;key3&quot; : [&quot;list_value1&quot;, &quot;list_value2&quot;, &quot;list_value3&quot;]}&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre id=&quot;code_1670945181201&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# HDFS에 테이블 폴더 만들기
$ hdfs dfs -mkdir /simple_schema_table_dir

# json 데이터 HDFS 경로에 넣기
$ hdfs dfs -put simple_schema.json /simple_schema_table_dir/

# 확인
$ hdfs dfs -ls /simple_schema_table_dir/
Found 1 items
-rw-r--r--   3 root supergroup  /simple_schema_table_dir/simple_schema.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;그럼 이제 이 테스트 데이터로 Hive 테이블을 만들어 보고 select 쿼리를 실행해보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1670947795428&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 테이블 생성
hive&amp;gt; create external table simple_schema_table(
    &amp;gt;  key1 struct&amp;lt;sub_key1:string, sub_key2:string&amp;gt;,
    &amp;gt;  key2 int,
    &amp;gt;  key3 array&amp;lt;string&amp;gt;
    &amp;gt; )
    &amp;gt; ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
    &amp;gt; LOCATION 'hdfs://namenode:8020/simple_schema_table_dir';
OK
Time taken: 1.164 seconds

# Metadata 업데이트
hive&amp;gt; msck repair table simple_schema_table;
OK
Time taken: 0.109 seconds

# select * 쿼리 실행  
hive&amp;gt; select * from simple_schema_table;
OK
{&quot;sub_key1&quot;:&quot;sub_value1&quot;,&quot;sub_key2&quot;:&quot;sub_value2&quot;}       1357    [&quot;list_value1&quot;,&quot;list_value2&quot;,&quot;list_value3&quot;]
Time taken: 2.216 seconds, Fetched: 1 row(s)

# Struct, Array select 쿼리 실행
hive&amp;gt; select key1.sub_key2, key3[1] from simple_schema_table;
OK
sub_value2      list_value2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Complex Json 데이터 create table 쿼리 자동 생성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;하지만 아주 복잡하고 key 값만 총 100개 이상인 Json 데이터의 경우 어떻게 해야할까요? 위의 방법대로 하면 100 이상의 key 값들을 모두 명시하고 타입을 정의해줘야 합니다. 할수는 있지만 상당히 귀찮고, 시간이 많이 걸리기 때문에 할 엄두가 나지 않을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이러한 문제를 해결하기 위해 Json 스키마를 파악한 뒤 create table 쿼리까지 자동 생성해주는 오픈 소스가 있습니다. 아래 Github 링크에서 git clone을 통해 다운받아 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;u&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://github.com/quux00/hive-json-schema&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/quux00/hive-json-schema&lt;/a&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1671035175450&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - quux00/hive-json-schema: Tool to generate a Hive schema from a JSON example doc&quot; data-og-description=&quot;Tool to generate a Hive schema from a JSON example doc - GitHub - quux00/hive-json-schema: Tool to generate a Hive schema from a JSON example doc&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/quux00/hive-json-schema&quot; data-og-url=&quot;https://github.com/quux00/hive-json-schema&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lMUXv/hyQTHazwup/MEw9wjg6LPuLdpRHM4idS0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/quux00/hive-json-schema&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/quux00/hive-json-schema&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lMUXv/hyQTHazwup/MEw9wjg6LPuLdpRHM4idS0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - quux00/hive-json-schema: Tool to generate a Hive schema from a JSON example doc&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Tool to generate a Hive schema from a JSON example doc - GitHub - quux00/hive-json-schema: Tool to generate a Hive schema from a JSON example doc&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;사용법은 어렵지 않습니다. 해당 Github에 나와있는 것처럼 java 명령어를 이용해 바로 실행시켜줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1671035522037&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ java -cp target/json-hive-schema-1.0.jar net.thornydev.JsonHiveSchema simple_schema.json&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;156&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUTyu7/btrTEO0gKk3/VwmO0WsktqTtKy2Sj9bj61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUTyu7/btrTEO0gKk3/VwmO0WsktqTtKy2Sj9bj61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUTyu7/btrTEO0gKk3/VwmO0WsktqTtKy2Sj9bj61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUTyu7%2FbtrTEO0gKk3%2FVwmO0WsktqTtKy2Sj9bj61%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;727&quot; height=&quot;156&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;156&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위의 결과처럼 create table 쿼리문을 자동 생성하여 출력해줍니다. 위의 예시는 간단한 Json 스키마를 사용했지만, 제가 작업했던 게임 데이터를 저장한 Json 파일의 경우 상당히 complex 스키마임에도 불구하고 아래처럼&amp;nbsp; 상당히 긴 쿼리를 만들어줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1322&quot; data-origin-height=&quot;778&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bF32EG/btrTDlxw8Ya/hFEtweMN5IacktkkAxv3x0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bF32EG/btrTDlxw8Ya/hFEtweMN5IacktkkAxv3x0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bF32EG/btrTDlxw8Ya/hFEtweMN5IacktkkAxv3x0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbF32EG%2FbtrTDlxw8Ya%2FhFEtweMN5IacktkkAxv3x0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1322&quot; height=&quot;778&quot; data-origin-width=&quot;1322&quot; data-origin-height=&quot;778&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;테이블 생성 쿼리문이 나왔다면 복사해서 Hive 쿼리로 실행해줍니다. Hive 쿼리가 정상적으로 실행되면, External 테이블의 경우 msck repair table 명령어로 Metadata 업데이트를 시켜주고 정상적으로 생성이 되었는지 위의 테스트 예시처럼 확인해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Hadoop Ecosystem/Hive</category>
      <category>Complex Json</category>
      <category>Hive</category>
      <category>json</category>
      <category>자동 생성</category>
      <category>테이블</category>
      <author>Taaewoo</author>
      <guid isPermaLink="true">https://taaewoo.tistory.com/76</guid>
      <comments>https://taaewoo.tistory.com/76#entry76comment</comments>
      <pubDate>Thu, 15 Dec 2022 01:46:22 +0900</pubDate>
    </item>
    <item>
      <title>[Hive] IntelliJ로 Runtime Debugging하기</title>
      <link>https://taaewoo.tistory.com/73</link>
      <description>&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이번 글에서는 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;Hive를 Runtime 중에 소스 코드 레벨에서 Debugging하는 방법에 대해 소개&lt;/span&gt;&lt;/b&gt;하겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Hive를 사용할 때 발생하는 에러는 보통 구글링을 해서 해결하곤 합니다. 하지만 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;구글링으로도 방법을 찾을 수 없을 때&lt;/span&gt;&lt;/b&gt; 근본적인 원인 파악을 위해 소스 코드 레벨에서 분석해야만 할 때가 있습니다. 아래의 방법으로 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;IntelliJ로 소스 코드 레벨에서 Debugging&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;을 한다면 좀 더 쉽고 정확한 문제 해결&lt;/span&gt;&lt;/b&gt;을 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;사전 준비&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Hive Debugging을 위해서 아래의 두가지를 준비합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;&amp;nbsp;IntelliJ 설치&lt;/b&gt;&lt;br /&gt;&lt;u&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://www.jetbrains.com/ko-kr/idea/download/#section=mac&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.jetbrains.com/ko-kr/idea/download/#section=mac&lt;/a&gt;&lt;/span&gt;&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Hive 소스 코드 다운로드 ( 사용하는 버전에 맞게 )&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;u&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://archive.apache.org/dist/hive/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://archive.apache.org/dist/hive/&lt;/a&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;다음으로는 IntelliJ에서 Hive 소스 코드로 프로젝트를 생성합니다. 아래와 같이 &lt;b&gt;&quot;Project from Existing Soureces&quot;&lt;/b&gt;를 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;442&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p3LKU/btrQ0XEWBCq/v4S7P21jDp1IUyj0lDCR21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p3LKU/btrQ0XEWBCq/v4S7P21jDp1IUyj0lDCR21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p3LKU/btrQ0XEWBCq/v4S7P21jDp1IUyj0lDCR21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp3LKU%2FbtrQ0XEWBCq%2Fv4S7P21jDp1IUyj0lDCR21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;614&quot; height=&quot;212&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;442&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;나타나는 창에서 &lt;b&gt;&quot;Create project from existing sources&quot;&lt;/b&gt; 선택하고 이어서 계속 Next를 눌러줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;764&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0AgsA/btrQZd3mXQ2/CCXSMVF5bXwtZuSCH81H51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0AgsA/btrQZd3mXQ2/CCXSMVF5bXwtZuSCH81H51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0AgsA/btrQZd3mXQ2/CCXSMVF5bXwtZuSCH81H51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0AgsA%2FbtrQZd3mXQ2%2FCCXSMVF5bXwtZuSCH81H51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;594&quot; height=&quot;313&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;764&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;프로젝트가 생성되었다면 &lt;b&gt;&quot;Run&quot;&lt;/b&gt; 메뉴에서 &lt;b&gt;&quot;Edit Configurations&quot;&lt;/b&gt;를 눌러줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;688&quot; data-origin-height=&quot;914&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZ79kz/btrQ0YDRCjG/euJghszkCIffRYufIKpEhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZ79kz/btrQ0YDRCjG/euJghszkCIffRYufIKpEhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZ79kz/btrQ0YDRCjG/euJghszkCIffRYufIKpEhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZ79kz%2FbtrQ0YDRCjG%2FeuJghszkCIffRYufIKpEhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;238&quot; height=&quot;316&quot; data-origin-width=&quot;688&quot; data-origin-height=&quot;914&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Configuration 창에서 아래와 같이 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;Host &amp;amp; Port&lt;/span&gt;&lt;/b&gt;와 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;&quot;JDK 5 - 8&quot;&lt;/span&gt;&lt;/b&gt;로 설정해줍니다. 이때 Host는 Hive를 실행하는 서버로 지정하고, Port의 경우 해당 서버가 이미 8000번을 사용한다면 다른 번호를 이용해줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;1068&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cO8wQU/btrQ0vIJHEK/KvM7NW6BnCqpYz6xkihYL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cO8wQU/btrQ0vIJHEK/KvM7NW6BnCqpYz6xkihYL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cO8wQU/btrQ0vIJHEK/KvM7NW6BnCqpYz6xkihYL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcO8wQU%2FbtrQ0vIJHEK%2FKvM7NW6BnCqpYz6xkihYL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;618&quot; height=&quot;374&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;1068&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Hive Runtime Debugging&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;사전 준비는 끝났다면 Hive를 실행할 서버에 접속해서 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;아래 명령어로 Hive CLI를 실행&lt;/span&gt;&lt;/b&gt;시켜줍니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;$ &lt;b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;HADOOP_CLIENT_OPTS=&quot;&lt;/span&gt;-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=&lt;span style=&quot;color: #009a87;&quot;&gt;8000&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&quot;&amp;nbsp;&lt;/span&gt;hive&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;저는 docker로 Hive 컨테이너를 실행시켰고 8000 port를 port forwarding 했습니다. 명령어를 실행하면 아래와 같이 Hive CLI가 계속 멈춰있는 상태인 것을 확인할 수 있습니다. ( docker 설정을 보려면 이 링크의 &lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;u&gt;&lt;a style=&quot;color: #0593d3;&quot; href=&quot;https://github.com/Taaewoo/Bigdata_Platform_on_Docker/blob/master/spark/docker-compose.yml&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;docker-compose.yml&lt;/a&gt;&lt;/u&gt;&lt;/span&gt;을 참고하세요. )&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2034&quot; data-origin-height=&quot;124&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxDZwZ/btrQZyTIbp6/KDGfB77vSOrEBJS86xqCt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxDZwZ/btrQZyTIbp6/KDGfB77vSOrEBJS86xqCt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxDZwZ/btrQZyTIbp6/KDGfB77vSOrEBJS86xqCt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxDZwZ%2FbtrQZyTIbp6%2FKDGfB77vSOrEBJS86xqCt0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;843&quot; height=&quot;51&quot; data-origin-width=&quot;2034&quot; data-origin-height=&quot;124&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 다음으로 IntelliJ에서 우측 상단의 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;Debugging 버튼(벌레 모양)을 눌러줍니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0jeos/btrQ0lfhZyQ/m0wc4DGurFSSUF0sKLkLK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0jeos/btrQ0lfhZyQ/m0wc4DGurFSSUF0sKLkLK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0jeos/btrQ0lfhZyQ/m0wc4DGurFSSUF0sKLkLK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0jeos%2FbtrQ0lfhZyQ%2Fm0wc4DGurFSSUF0sKLkLK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;290&quot; height=&quot;83&quot; data-origin-width=&quot;622&quot; data-origin-height=&quot;178&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;정상적으로 Debugging 모드에 들어갔다면 Connected 문구가 출력고 Hive CLI는 멈춰있던 상태에서 다시 실행됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2730&quot; data-origin-height=&quot;748&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/deoKjx/btrQ1fyF6Pg/4UndCLFUPzZIoK9xiTZM51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/deoKjx/btrQ1fyF6Pg/4UndCLFUPzZIoK9xiTZM51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/deoKjx/btrQ1fyF6Pg/4UndCLFUPzZIoK9xiTZM51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdeoKjx%2FbtrQ1fyF6Pg%2F4UndCLFUPzZIoK9xiTZM51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2730&quot; height=&quot;748&quot; data-origin-width=&quot;2730&quot; data-origin-height=&quot;748&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이제 IntelliJ에서 Hive 소스 코드 중 원하는 곳에 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;Break point&lt;/span&gt;&lt;/b&gt;를 지정하고 Hive CLI에서 특정 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;쿼리를 실행&lt;/span&gt;&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1780&quot; data-origin-height=&quot;318&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czerr9/btrQZhxWSUj/UrwLoIHQW2l3G3xaPkFJW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czerr9/btrQZhxWSUj/UrwLoIHQW2l3G3xaPkFJW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czerr9/btrQZhxWSUj/UrwLoIHQW2l3G3xaPkFJW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fczerr9%2FbtrQZhxWSUj%2FUrwLoIHQW2l3G3xaPkFJW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;737&quot; height=&quot;132&quot; data-origin-width=&quot;1780&quot; data-origin-height=&quot;318&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;340&quot; data-origin-height=&quot;46&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOKdIa/btrQ0wgD57k/BRdW3kJgqmHTKfR8RKjzlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOKdIa/btrQ0wgD57k/BRdW3kJgqmHTKfR8RKjzlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOKdIa/btrQ0wgD57k/BRdW3kJgqmHTKfR8RKjzlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOKdIa%2FbtrQ0wgD57k%2FBRdW3kJgqmHTKfR8RKjzlK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;281&quot; height=&quot;38&quot; data-origin-width=&quot;340&quot; data-origin-height=&quot;46&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;그러면 IntelliJ에서 우리가 원하던 Break point에서 멈추게 됩니다. &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Debugging 기능들을 이용하여 step을 옮길 수 있고 각 지점에서 사용되는 변수의 값들을 확인&lt;/span&gt;&lt;/b&gt;할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2682&quot; data-origin-height=&quot;1762&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vJB2f/btrQZWfMs5C/4d3sF0BKTOijFiMp6o1Juk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vJB2f/btrQZWfMs5C/4d3sF0BKTOijFiMp6o1Juk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vJB2f/btrQZWfMs5C/4d3sF0BKTOijFiMp6o1Juk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvJB2f%2FbtrQZWfMs5C%2F4d3sF0BKTOijFiMp6o1Juk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;755&quot; height=&quot;496&quot; data-origin-width=&quot;2682&quot; data-origin-height=&quot;1762&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이러한 방식으로 Hive 수행 과정을 소스 코드 레벨에서 Debugging한다면 동작 과정을 상세하게 이해하거나 해결하기 어려운 이슈에 대해서 원인 파악 및 문제 해결하는데 도움이 될 것이라 생각합니다.&lt;/p&gt;</description>
      <category>Hadoop Ecosystem/Hive</category>
      <category>debugging</category>
      <category>Hive</category>
      <category>IntelliJ</category>
      <category>디버깅</category>
      <author>Taaewoo</author>
      <guid isPermaLink="true">https://taaewoo.tistory.com/73</guid>
      <comments>https://taaewoo.tistory.com/73#entry73comment</comments>
      <pubDate>Sat, 12 Nov 2022 15:47:51 +0900</pubDate>
    </item>
    <item>
      <title>[Hive] limit 사용 시 leastNumRows 에러 발생 이슈</title>
      <link>https://taaewoo.tistory.com/70</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 Hive 쿼리를 limit 절과 함께 사용할 때 발생하는 leastNumRows 에러 발생 이슈와 해결 과정에 대해 공유하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제 발견&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Hive 테이블을 select 할 때 limit 절을 사용하면 에러가 발생하는 문제를 발견하게 되었습니다. &lt;b&gt;Hive CLI에서 실행&lt;/b&gt;시킨 쿼리 예제와 발생하는 에러는 아래와 같았습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1666887369887&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;select AA_COL from AA_TABLE
where partition_p=p1
limit 35;&lt;/code&gt;&lt;/pre&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;java.io.IOException: org.apache.hadoop.hive.ql.metadata.HiveException:&lt;/span&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;leastNumRows check failed&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제 상황&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;다양한 케이스들에 따라 위의 에러 발생 여부가 달랐습니다. 일단 사전에 설정되었던 Hive 옵션 중 하나는 &lt;b&gt;&quot;hive.fetch.task.conversion&quot;&lt;/b&gt; 으로 Fetch Task 작동 없이 모두 MR 작업이 수행되도록 &lt;b&gt;&quot;none&quot;&lt;/b&gt;으로 설정했다는 점, &lt;b&gt;Hive 엔진은 Tez를 사용&lt;/b&gt;했다는 점 참고바랍니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;쿼리 성공 케이스&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;hive.fetch.task.conversion 옵션을 more로 설정해 MR이 아닌 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Fetch Task 작업이 수행되었을 때&lt;/span&gt;&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;Tez 작업이 &lt;span&gt;아닌&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Spark를 이용한 Hive 쿼리를 실행시켰을 때.&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;limit 수를 2 이하&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로 했을 때.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;limit 없이 테이블 전체를 select &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;할 때.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;에러 발생 케이스&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Tez 엔진으로 MR 작업&lt;/span&gt;&lt;/b&gt;이 수행될 때.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;limit 수를 3 이상&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;으로 했을 때&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;에러가 발생할 때 나타났던 주요 특징으로는, Hive 쿼리가 실행될 때가 아니라 쿼리 결과를 가져와 출력하는 Fetch 과정에서 에러가 발생했다는 점입니다. &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;여기서 추측할 수 있는 것은 Hive 쿼리 수행 자체는 크게 문제가 없다는 점이었습니다. &lt;/span&gt;&lt;/b&gt;아래의 Hive CLI 출력과 Stack trace를 보면 Fetch 과정에서 문제가 발생한 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;width: 100%; overflow: auto; font-size: 0.85rem;&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 98.6051%; height: 270px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;width: 842.017px; height: 10px;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;b&gt;Hive CLI Console&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 842.017px; height: 21px;&quot;&gt;----------------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;&amp;nbsp; VERTICES&amp;nbsp; &amp;nbsp; &amp;nbsp; MODE&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;STATUS&amp;nbsp; &amp;nbsp; &amp;nbsp; TOTAL&amp;nbsp; &amp;nbsp; COMPLETED&amp;nbsp; &amp;nbsp;RUNNING&amp;nbsp; &amp;nbsp; PENDING&amp;nbsp; &amp;nbsp;FAILED&amp;nbsp; &amp;nbsp;KILLED&lt;br /&gt;----------------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;&amp;nbsp; &amp;nbsp; Map 1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ....&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;SUCCESS&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;br /&gt;----------------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;VERTICES :&amp;nbsp; &amp;nbsp;01/01.&amp;nbsp; &amp;nbsp;[===============================&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;======&amp;gt;&amp;gt;]&amp;nbsp; &amp;nbsp;100%&lt;/span&gt;&amp;nbsp; &amp;nbsp;&lt;br /&gt;----------------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;Status : DAG finished successfully in 5.67 seconds&lt;br /&gt;&lt;br /&gt;....&lt;br /&gt;&lt;br /&gt;OK&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;java.io.IOException:org.apache.hadoop.hive.ql.metadata.HiveException:&lt;/span&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;leastNumRows check failed&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;원인 분석&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;안타깝게도 &lt;b&gt;&quot;leastNumRows check failed&quot;&lt;/b&gt; 관련 에러는 아무리 google에 검색해도 비슷한 게시물이 하나도 나오지 않았습니다.... 그래서 결국에는 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;Stack trace를 참고해 Hive 소스 코드 분석으로 에러의 원인을 파악&lt;/span&gt;&lt;/b&gt;해야만 했습니다. 에러에 대한 Stack trace와 소스 코드 분석 내용은 아래와 같습니다.&lt;/p&gt;
&lt;div style=&quot;width: 100%; overflow: auto; font-size: 0.85rem;&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 96.2792%; height: 159px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;width: 842.017px; height: 10px;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;b&gt;hiveserver2.log&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 842.017px; height: 21px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;java.io.IOException:org.apache.hadoop.hive.ql.metadata.HiveException:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;leastNumRows check failed&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp; at org.apache.hadoop.hive.ql.exec.FetchTask.fetch(&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;FetchTask.java&lt;/span&gt;&lt;/b&gt;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; at org.apache.hadoop.hive.ql.Driver.getResult(&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Driver.java&lt;/b&gt;&lt;/span&gt;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; at org.apache.hadoop.hive.ql.reexec.ReExecDriver.getResult(&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;ReExecDriver.java&lt;/b&gt;&lt;/span&gt;)&lt;br /&gt;&amp;nbsp; &amp;nbsp; at org.apache.hadoop.hive.cli.CliDriver.processLocalCmd(CliDriver.java)&lt;br /&gt;&amp;nbsp; &amp;nbsp; ....&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://archive.apache.org/dist/hive/hive-3.1.0/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;i&gt;Hive 3.1.0 Source code from Archive&lt;/i&gt;&lt;/a&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;FetchTask.java&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1667140542993&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public boolean fetch(List res) throws IOException {
    sink.reset(res);
    int rowsRet = work.getLeastNumRows();
    if (rowsRet &amp;lt;= 0) {
      rowsRet = work.getLimit() &amp;gt;= 0 ? Math.min(work.getLimit() - totalRows, maxRows) : maxRows;
    }
    try {
      if (rowsRet &amp;lt;= 0 || work.getLimit() == totalRows) {
        fetch.clearFetchContext();
        return false;
      }
      boolean fetched = false;
      while (sink.getNumRows() &amp;lt; rowsRet) {
        if (!fetch.pushRow()) {
          if (work.getLeastNumRows() &amp;gt; 0) {
            throw new HiveException(&quot;leastNumRows check failed&quot;);
          }

          // Closing the operator can sometimes yield more rows (HIVE-11892)
          fetch.closeOperator();

          return fetched;
        }
        fetched = true;
      }
  ....&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fetch 과정에서 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;row 수 관련 조건으로 인해 &quot;leastNumRows&quot; 에러 발생&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Stack trace에서 에러가 발생한 FetchTask.java 아래의 코드 내용은 Hive CLI에서 결과 값을 불러오는 내용이라 원인 분석에는 도움이 되지 않았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;그래서 원인을 찾기 위해 Hive 쿼리의 limit 절과 관련된 옵션들을 찾아봤고, &quot;hive.limit.~~&quot; 으로 시작되는 옵션들을 아래와 같이 존재했습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 99.7672%; height: 50px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;width: 99.8834%; height: 10px;&quot; colspan=&quot;2&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;b&gt;Hive Limit Option&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;width: 28.3216%; height: 10px;&quot;&gt;hive.limit.optimize.enable&lt;/td&gt;
&lt;td style=&quot;width: 71.5618%; height: 10px;&quot;&gt;&amp;nbsp;Whether to enable to optimization to trying a smaller subset of data for simple LIMIT first.&lt;br /&gt;&lt;b&gt;- Default Value:&amp;nbsp;false&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;width: 28.3216%; height: 10px;&quot;&gt;hive.limit.row.max.size&lt;/td&gt;
&lt;td style=&quot;width: 71.5618%; height: 10px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;When trying a smaller subset of data for simple LIMIT, how much size we need to guarantee each row to have at least.&lt;br /&gt;&lt;b&gt;- Default Value: 100000&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;width: 28.3216%; height: 10px;&quot;&gt;hive.limit.optimize.limit.file&lt;/td&gt;
&lt;td style=&quot;width: 71.5618%; height: 10px;&quot;&gt;&amp;nbsp;When trying a smaller subset of data for simple LIMIT, maximum number of files we can sample.&lt;br /&gt;&lt;b&gt;- Default Value:&amp;nbsp;10&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;width: 28.3216%; height: 10px;&quot;&gt;hive.limit.optimize.fetch.max&lt;/td&gt;
&lt;td style=&quot;width: 71.5618%; height: 10px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;Maximum number of rows allowed for a smaller subset of data for simple LIMIT, if it is a fetch query. Insert queries are not restricted by this limit.&lt;br /&gt;&lt;b&gt;- Default Value:&amp;nbsp;50000&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위의 옵션 중 &quot;hive.limit.row.max.size&quot;의 의미를 정확하게는 알 수 없었습니다. 하지만 &quot;hive.limit.optimize.enable&quot; 옵션에 대해 &quot;false&quot;로 설정 후 테스트를 진행했을 때 정상적으로 수행되었습니다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;쿼리 성공 케이스&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;....&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;(+) &quot;hive.limit.optimize.enable&quot; 옵션을 false&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;로 설정 후 실행시켰을 때&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;&amp;nbsp;이를 통해 Hive의 limit 절 쿼리를 수행할 때 optimization을 하는 과정에서 발생하는 문제라는 것을 알게 되었습니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Limit optimization의 동작 원리&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위의 사실들을 알아냈고 문제 해결을 하기 위해 &lt;b&gt;Hive가 limit 절 쿼리를 어떻게 optimization 하는지 원리를 알아야 했습니다.&lt;/b&gt;&amp;nbsp;그래서 관련 내용들을 Hive 소스 코드에서 확인하려고 했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Optimizer.java&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1667218730384&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...

if (HiveConf.getBoolVar(hiveConf, HiveConf.ConfVars.HIVELIMITOPTENABLE)) {
    transformations.add(new GlobalLimitOptimizer());
}

...&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;우선 &quot;hive.limit.optimize.enable&quot; 옵션을 true로 설정했을 때 Hive에서는 GlobalLimitOptimizer 객체를 추가합니다. 그래서 다시 GlobalLimitOptimizer에 대해 조사하던 중 아래 문구를 발견할 수 있었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciQqdg/btrQrtjYUv2/VFW2HngAMGEY65UgGRdLuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciQqdg/btrQrtjYUv2/VFW2HngAMGEY65UgGRdLuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciQqdg/btrQrtjYUv2/VFW2HngAMGEY65UgGRdLuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciQqdg%2FbtrQrtjYUv2%2FVFW2HngAMGEY65UgGRdLuK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;737&quot; height=&quot;96&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;250&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위의 내용을 통해, &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;Hive의 limit optimization은 테이블의 실제 파일을 몇 개만 읽어 sampling 하고 그 안에서 limit 수만큼만 결과로 &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;보여준다는 것을 알게 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&amp;nbsp;테스트 진행&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 테이블에 (8개 Row가 있는 parquet) + (2개 Row가 있는 parquet) 저장&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1620&quot; data-origin-height=&quot;976&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xHrdG/btrP3zZVJvM/i1kMBkEfEgySrg4q6RgPMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xHrdG/btrP3zZVJvM/i1kMBkEfEgySrg4q6RgPMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xHrdG/btrP3zZVJvM/i1kMBkEfEgySrg4q6RgPMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxHrdG%2FbtrP3zZVJvM%2Fi1kMBkEfEgySrg4q6RgPMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;405&quot; height=&quot;976&quot; data-origin-width=&quot;1620&quot; data-origin-height=&quot;976&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;총 10개 Row&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;limit 1 ~ 8까지 에러 없이 정상 수행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;limit 9 이상부터 동일한 에러 발생&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 테이블에 (8개 Row가 있는 parquet) + (2개 Row가 있는 parquet x 5) 저장&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2446&quot; data-origin-height=&quot;1002&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5Lpgn/btrP3LFOPyC/NKBBLVY5w1n5xyuplKHsAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5Lpgn/btrP3LFOPyC/NKBBLVY5w1n5xyuplKHsAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5Lpgn/btrP3LFOPyC/NKBBLVY5w1n5xyuplKHsAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5Lpgn%2FbtrP3LFOPyC%2FNKBBLVY5w1n5xyuplKHsAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;621&quot; height=&quot;254&quot; data-origin-width=&quot;2446&quot; data-origin-height=&quot;1002&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;총 18개 Row&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;limit 1 ~ 10까지 에러 없이 정상 수행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;limit 11 이상부터 동일한 에러 발생&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이 테스트들을 미루어 보았을 때, &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;특정 파일 몇 개를 sampling해서 limit 수를 만족하지 못할 때 에러가 발생&lt;/span&gt;&lt;/b&gt;한다는 것을 대충 알 수 있었지만, &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;어떤 파일을? 몇개를? sampling 하는지에 대한 상세한 과정을 알 수 없었습니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Hive CLI Debug Log 분석 및 문제 해결&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Hive의 데이터 sampling 과정에 대해 조금이라도 힌트를 얻기 위해 Hive CLI를 Debug 모드로 실행해 Log를 확인했습니다. 명령어는 아래와 같습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;$ hive --hiveconf hive.root.logger=DEBUG,console&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Hive의 쿼리 처리 과정을 상세하게 공부를 하고, Log를 한 줄씩 분석하기 시작했습니다. &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;확실하게 이론적인 부분에 먼저 접근한 뒤 실제 Log를 읽으니 더 많은 부분에 대해 이해&lt;/span&gt;&lt;/b&gt;할 수 있었고, 그 결과 sampling 관련 Log를 발견할 수 있었습니다.&lt;/p&gt;
&lt;div style=&quot;width: 100%; overflow: auto; font-size: 0.85rem;&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 111.86%; height: 165px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;width: 842.017px; height: 10px;&quot;&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;&lt;b&gt;Hive CLI Debug Log&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 842.017px; height: 21px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;INFO&lt;/span&gt; &lt;span style=&quot;color: #8a3db6;&quot;&gt;optimizer.GenMapRedUtils:&lt;/span&gt; Try to reduce input size for 'limit' &lt;span style=&quot;color: #009a87;&quot;&gt;sizeNeeded&lt;/span&gt;: &lt;span style=&quot;color: #006dd7;&quot;&gt;2000000&lt;/span&gt; file limit : 10&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;INFO&lt;/span&gt; &lt;span style=&quot;color: #8a3db6;&quot;&gt;optimizer.SamplePruner:&lt;/span&gt; Path pattern = &lt;span style=&quot;color: #006dd7;&quot;&gt;hdfs://nameservice1/data_path/AA_TABLE/partition_p=p1/*&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;INFO&lt;/span&gt; &lt;span style=&quot;color: #8a3db6;&quot;&gt;optimizer.SamplePruner:&lt;/span&gt; Got file: &lt;span style=&quot;color: #006dd7;&quot;&gt;hdfs://nameservice1/data_path/AA_TABLE/&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;partition_p=p1/file1.parquet&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;DEBUG&lt;/span&gt; &lt;span style=&quot;color: #8a3db6;&quot;&gt;optimizer.GenMapRedUtils:&lt;/span&gt; Adding &lt;span style=&quot;color: #006dd7;&quot;&gt;hdfs://nameservice1/data_path/AA_TABLE/&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;partition_p=p1/file1.parquet &lt;span style=&quot;color: #333333;&quot;&gt;of table AA_TABLE&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;DEBUG&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #8a3db6;&quot;&gt;optimizer.GenMapRedUtils:&lt;/span&gt; Information added for path&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;hdfs://nameservice1/data_path/AA_TABLE/partition_p=p1/file1.parquet&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;&amp;nbsp;Sampling 관련 작업들은 Hive의 optimization 과정에서 이루어진다는 것을 알 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;( Hive optimization 관련 내용은 &lt;/span&gt;&lt;a href=&quot;https://taaewoo.tistory.com/77&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;&lt;u&gt;[Hive] Compile 상세 과정 #2 - Optimization 종류와 소스 코드 분석&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/a&gt; 글을 참고해주세요. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;&amp;nbsp;그리고 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;가&lt;/span&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;장&lt;/b&gt; 핵심적인 log로써 테이블 경로에 있는 파일들을 직접 접근하는 부분을 발견&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;할 수 있었습니다. 위의 log 내용을 통해 첫 번째 테스트 과정에서 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;8개 Row를 가진 &quot;file1.parquet&quot; 파일 1개만 sampling에 사용&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;되었다는 것을 알 수 있었습니다. 그래서 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;8보다 큰 숫자로 limit을 설정했을 때 에러가 발생&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; font-size: 16px; letter-spacing: 0px;&quot;&gt;한 것입니다. 그렇다면 왜 1개의 파일만 sampling에 사용되었는지 알기 위해 위의 log들이 기록되는 소스 코드를 분석했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;GenMapRedUtils.java&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;INFO&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #8a3db6;&quot;&gt;optimizer.GenMapRedUtils:&lt;/span&gt;&amp;nbsp;Try to reduce input size for 'limit'&amp;nbsp;&lt;span style=&quot;color: #009a87;&quot;&gt;sizeNeeded&lt;/span&gt;:&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;2000000&lt;/span&gt;&amp;nbsp;file limit : 10&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1667408082730&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (parseCtx.getGlobalLimitCtx().isEnable()) {
      
      ...
      long sizePerRow = HiveConf.getLongVar(parseCtx.getConf(),
            HiveConf.ConfVars.HIVELIMITMAXROWSIZE);
        
      sizeNeeded = (parseCtx.getGlobalLimitCtx().getGlobalOffset()
            + parseCtx.getGlobalLimitCtx().getGlobalLimit()) * sizePerRow;
        
        
      ...
      LOG.info(&quot;Try to reduce input size for 'limit' &quot; +
              &quot;sizeNeeded: &quot; + sizeNeeded +
              &quot;  file limit : &quot; + fileLimit);
      ...&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;GenMapRedUtils에서 log에서 발견된 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;sizeNeeded 변수&lt;/span&gt;&lt;/b&gt;의 계산 방법을 확인할 수 있었습니다. 계산 방법은 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;(limit 수) x (hive.limit.row.max.size)&lt;/span&gt;&lt;/b&gt; 입니다. limit 수를 Row 수라고 생각하여 최대 사이즈만큼 곱해준 값입니다. sizeNeeded 변수가 sampling에 필요한 값이라고 의심되지만, 아직 확인된 게 없으니 일단 넘어가겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;SamplePruner.java&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;INFO&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #8a3db6;&quot;&gt;optimizer.SamplePruner:&lt;/span&gt;&amp;nbsp;Path pattern =&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;hdfs://nameservice1/data_path/AA_TABLE/partition_p=p1/*&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;INFO&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #8a3db6;&quot;&gt;optimizer.SamplePruner:&lt;/span&gt;&amp;nbsp;Got file:&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;hdfs://nameservice1/data_path/AA_TABLE/&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;partition_p=p1/file1.parquet&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1667566951940&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    ...
    LOG.info(&quot;Path pattern = &quot; + pathPattern);
    FileStatus srcs[] = fs.globStatus(new Path(pathPattern));
    Arrays.sort(srcs);

    boolean hasFile = false, allFile = true;

    for (FileStatus src : srcs) {
      if (sizeLeft &amp;lt;= 0) {
        allFile = false;
        break;
      }
      
      ...
        LOG.info(&quot;Got file: &quot; + src.getPath());
        hasFile = true;
        retPathList.add(src.getPath());
        sizeLeft -= src.getLen();
        if (retPathList.size() &amp;gt;= fileLimit &amp;amp;&amp;amp; sizeLeft &amp;gt; 0) {
          return null;
        }
      ...&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;SamplePruner.java에서 그토록 원하던 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;sample 파일 선별 과정을 확인&lt;/span&gt;&lt;/b&gt;할 수 있었습니다. 파일 선별 과정을 요약하면 이렇습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;- 테이블 경로의 모든 파일을 srcs 배열에 저장&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;- srcs 배열을 파일명 순서로 정렬하고 반복문 실행&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;- 이때 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;sizeLeft 변수가 0 이하면 반복문 종료&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;- 파일을 List에 추가 후 파일 크기만큼 sizeLeft 감소&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;여기서 sizeLeft 변수는 GenMapRedUtils.java에서 사용된 sizeNeeded라는 것을 코드를 통해 확인할 수 있습니다. 즉 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;(limit 수) x (hive.limit.row.max.size)로 계산된 값이 sampling 할 총 파일 크기입니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;결국 문제의 원인은 sizeNeeded 변수 값에 있었습니다. hive.limit.row.max.size 옵션의 default 값은 100,000으로 100KB입니다. 하지만 테이블의 데이터 파일을 확인한 결과 Row당 파일크기는 300KB까지 나가기도 했습니다. 결국 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;limit 20을 만족할만한 파일 sampling을 할 수 없었습니다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;그래서 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;hive.limit.row.max.size 옵션을 넉넉하게 3MB인 3,000,000으로 설정&lt;/b&gt;&lt;/span&gt;했습니다. 쿼리 실행 시 파일 sampling이 충분히 되어 limit 절을 이용하더라도 이전과 같은 에러가 발생하지 않았습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;- limit 절을 포함한 쿼리 수행 시 에러 발생&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;- limit optimization 수행 시 에러 발생&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;- limit optimization의 파일 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;sampling 과정에서&lt;/span&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;용량 조건으로 인해 부족한 sampling 확인&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;hive.limit.row.max.size 옵션 값 설정&lt;/span&gt;&lt;/b&gt;으로 문제 해결&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;a href=&quot;https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties&quot;&gt;https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Hadoop Ecosystem/Hive</category>
      <category>Hive</category>
      <category>leastNumRows</category>
      <category>Limit</category>
      <category>Optimization</category>
      <category>Sampling</category>
      <author>Taaewoo</author>
      <guid isPermaLink="true">https://taaewoo.tistory.com/70</guid>
      <comments>https://taaewoo.tistory.com/70#entry70comment</comments>
      <pubDate>Fri, 4 Nov 2022 23:24:15 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm][KMP] 28. Find the Index of the First Occurrence in a String</title>
      <link>https://taaewoo.tistory.com/69</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;KMP 알고리즘이란?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&amp;nbsp;문자열을 한개씩 비교하는 것이 아니라 지금까지 비교한 문자열 중 접두사, 접미사가 같을 경우 중간 과정을 생략하고 비교하는 알고리즘&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;시간 복잡도&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;\( O(n + m) \)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제 링크&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://leetcode.com/problems/find-the-index-of-the-first-occurrence-in-a-string/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://leetcode.com/problems/find-the-index-of-the-first-occurrence-in-a-string/&lt;/a&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1588&quot; data-origin-height=&quot;1438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mNm1U/btrPkpQE1Qc/gsh4g4KMizXFGmIOaJunu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mNm1U/btrPkpQE1Qc/gsh4g4KMizXFGmIOaJunu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mNm1U/btrPkpQE1Qc/gsh4g4KMizXFGmIOaJunu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmNm1U%2FbtrPkpQE1Qc%2Fgsh4g4KMizXFGmIOaJunu1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;668&quot; height=&quot;605&quot; data-origin-width=&quot;1588&quot; data-origin-height=&quot;1438&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이번 문제는 주어진 문자열에서 sub 문자열이 몇번 째 index에 존재하는지를 답안으로 내야합니다. 단순하게 생각하면 단순 문자열 비교로 보일 수 있지만, 주어진 조건을 보면 문자열의 길이가 10000입니다. 그래서 단순 비교를 한다면 당연히 시간초과가 발생합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;단순 전체 비교 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;우선 단순 비교로 문제를 푸는 방법을 소개하겠습니다. &lt;b&gt;전체 문자열의 시작 문자부터 Sub 문자열의 문자를 하나씩 비교&lt;/b&gt;합니다. 이렇게 Sub 문자열의 전체가 일치할 때까지 진행합니다. 단순 비교의 시간 복잡도는 전체 문자열의 크기 &lt;span&gt;\( N \) 만큼 for 문을 사용하고 Sub 문자열의 크기 &lt;span&gt;\( M \) 만큼 for문을 사용하기 때문에 &lt;span&gt;\( O(NM) \) 가 됩니다. 이 때 \( M \) 의 크기가 \( N \)이 된다면 \( O(N^2) \) 까지도 증가하게 됩니다. 아래 예시에서는 총 14번의 문자 비교가 필요합니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1094&quot; data-origin-height=&quot;1696&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Aswyw/btrPkrHQavq/kPcbWk8y6W0ZOFBAgcYSu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Aswyw/btrPkrHQavq/kPcbWk8y6W0ZOFBAgcYSu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Aswyw/btrPkrHQavq/kPcbWk8y6W0ZOFBAgcYSu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAswyw%2FbtrPkrHQavq%2FkPcbWk8y6W0ZOFBAgcYSu0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;386&quot; height=&quot;598&quot; data-origin-width=&quot;1094&quot; data-origin-height=&quot;1696&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;KMP 알고리즘 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;우리는 위의 경우처럼 전체 문자열 N개를 하나하나 비교하고 싶지 않습니다. &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;효율적으로 비교가 필요 없는 부분은 아래처럼 생략&lt;/b&gt;&lt;/span&gt;하며 진행하고 싶습니다. 하지만 아래처럼 sub 문자열을 다시 처음부터 비교시키기엔 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;예외 상황&lt;/span&gt;&lt;/b&gt;이 있습니다. 바로 지금까지 비교해서 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;일치한 &lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;문자&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;열 중 중복되는 문자열이 존재하는 경우&lt;/span&gt;&lt;/b&gt;입니다. 이러한 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;예외 상황을 고려해 효율적으로 중간 과정을 생략한 알고리즘이 바로 KMP 알고리즘&lt;/b&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;844&quot; data-origin-height=&quot;614&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d46Tks/btrPmEzXc0s/liXZHzDfkSlcAqspPoOSrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d46Tks/btrPmEzXc0s/liXZHzDfkSlcAqspPoOSrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d46Tks/btrPmEzXc0s/liXZHzDfkSlcAqspPoOSrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd46Tks%2FbtrPmEzXc0s%2FliXZHzDfkSlcAqspPoOSrk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;413&quot; height=&quot;300&quot; data-origin-width=&quot;844&quot; data-origin-height=&quot;614&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;KMP 알고리즘의 핵심은 지금까지 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;연속으로 일치한 문자열에서 접두사와 접미사가 같은 경우가 있을 때 중간 과정을 생략하고 접미사를 접두사의 위치로 점프&lt;/span&gt;&lt;/b&gt;시키는 것입니다. 접두사와 접미사를 사용하는 이유는 위에서 말한 중복 상황을 고려하기 위함입니다. 글로는 이해가 어려울 수 있습니다. 아래 그림에서 단순 비교 방법과 비교하여 원리를 알면 더 이해하기 쉬울 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2002&quot; data-origin-height=&quot;1766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bar5vf/btrPhn7fUp5/yi2nfgBgaFYpX39mUnXFt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bar5vf/btrPhn7fUp5/yi2nfgBgaFYpX39mUnXFt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bar5vf/btrPhn7fUp5/yi2nfgBgaFYpX39mUnXFt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbar5vf%2FbtrPhn7fUp5%2Fyi2nfgBgaFYpX39mUnXFt1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;787&quot; height=&quot;694&quot; data-origin-width=&quot;2002&quot; data-origin-height=&quot;1766&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;KMP 알고리즘은 문자열 비교 중 일치하지 않는다면, 이전 문자열에서 접두사와 접미사 길이를 확인하고 접미사 다음 문자로 다시 비교합니다. 그림과 같이 접미사 부분인 &quot;ab&quot;를 제외하고 &quot;c&quot;부터 일치 여부를 다시 검사합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;그렇다면 만약 여기서 sub 문자열의 접미사 다음 문자가 일치하지 않는 문제가 발생하면 어떻게 될까요?&amp;nbsp; 그러면 &lt;b&gt;접미사를 다시 &quot;Sub 문자열2&quot; 로 생각하고 &quot;Sub 문자열2&quot; 에서 서로 일치하는 접미사와 접두사를 찾고&lt;/b&gt; 해당 접미사 다음 문자열부터 비교하면 됩니다. 만약 없다면 Sub 문자열 처음부터 다시 비교하면 됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;접두사, 접미사가 일치하는 최대 길이 계산&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위의 KMP 알고리즘을 적용하기 위해 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Sub 문자열의 각 문자열 위치에서 접두사, 접미사가 일치하는 최대 길이를 사전에 계산&lt;/span&gt;&lt;/b&gt;합니다. 이 때 이 값을 &lt;b&gt;&quot;Longest Proper Prefix&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #4d5156;&quot;&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;which is Suffix&quot;라고 하여 LPS 배열&lt;/b&gt;이라고 부릅니다.&lt;/span&gt; 하지만 LPS 배열을 계산할 때 주의할 점은 Sub 문자열 또한 결국에는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;문자열의 비교 과정이기 때문에 위에서 소개한 원리가 그대로 적용&lt;/b&gt;&lt;/span&gt;이 됩니다. LPS 배열의 이전 index 값들을 이용하여 LPS 배열의 새로운 index 값을 구합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;930&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dV7Vh8/btrPmDgK3u4/Og1Ua1819Pk2sLCtpAThi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dV7Vh8/btrPmDgK3u4/Og1Ua1819Pk2sLCtpAThi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dV7Vh8/btrPmDgK3u4/Og1Ua1819Pk2sLCtpAThi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdV7Vh8%2FbtrPmDgK3u4%2FOg1Ua1819Pk2sLCtpAThi0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;277&quot; height=&quot;412&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;930&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Python&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;그래서 KMP 알고리즘을 적용한 LeetCode 28번 문제의 풀이 코드는 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1666534757696&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Solution:
    def strStr(self, haystack: str, needle: str) -&amp;gt; int:
        lps = [0] * len(needle)
        
        j = 0
        for i in range(1,len(needle)):
            while not( j == 0 or needle[i] == needle[j] ):
                j = lps[j-1]
                
            if needle[i] == needle[j]:
                j += 1
                lps[i] = j
                
        j = 0
        for i in range(0,len(haystack)):
            while not( j == 0 or haystack[i] == needle[j] ):
                j = lps[j-1]
                
            if haystack[i] == needle[j]:
                if j == len(needle)-1:
                    return i - j
                j += 1
        return -1&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm 문제 풀이/LeetCode</category>
      <category>algorithm</category>
      <category>KMP</category>
      <category>LeetCode</category>
      <category>LPS</category>
      <category>문자열 비교</category>
      <category>알고리즘</category>
      <category>접두사</category>
      <category>접미사</category>
      <author>Taaewoo</author>
      <guid isPermaLink="true">https://taaewoo.tistory.com/69</guid>
      <comments>https://taaewoo.tistory.com/69#entry69comment</comments>
      <pubDate>Sun, 23 Oct 2022 23:35:57 +0900</pubDate>
    </item>
    <item>
      <title>[NiFi] Json 데이터의 동적 크기 Array 전처리하기 (Base64 decoding)</title>
      <link>https://taaewoo.tistory.com/68</link>
      <description>&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이번 글에서는 NiFi에서 Json 파일을 전처리하는 방법 중 하나에 대해 소개하겠습니다. NiFi에서 Json 데이터를 처리하기 위한 다양한 Procssor들이 존재합니다. 하지만 Json 데이터가 단순히 key / value 값들만 존재한다면 처리가 쉽겠지만, 경우에 따라서는 Json 데이터에 Array 타입이 존재할 수 있습니다. 그리고 &lt;span style=&quot;color: #ee2323;&quot;&gt;Array의 크기가 고정이라면 다행이지만 데이터마다 동적인 크기를 가질 때는 상당히 골치 아파집니다.&lt;/span&gt; 아래 내용에서 이와 같은 동적인 크기의 Array 타입을 처리하는 방법을 제시하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Json 데이터 예시&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이번 글에서 다룰 Json 데이터의 구조와 예시를 보여드리겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;1034&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8M2Rg/btrMrRV5t9S/Wez2VlYY3hjfS9SrDMueMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8M2Rg/btrMrRV5t9S/Wez2VlYY3hjfS9SrDMueMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8M2Rg/btrMrRV5t9S/Wez2VlYY3hjfS9SrDMueMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8M2Rg%2FbtrMrRV5t9S%2FWez2VlYY3hjfS9SrDMueMK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;439&quot; height=&quot;376&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;1034&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Json의 가장 최상위에 A, B라는 key 값들이 존재합니다. A는 Array 타입으로써 index 당&amp;nbsp; AA, BB, CC라는 key값들로 String 타입의 Value들을 가집니다. 그리고 A는 동적인 크기를 가지기 때문에 위의 그림에서는 index가 3까지밖에 없지만, 데이터에 따라 10개, 100개도 존재할 수 있습니다. B는 단순히 String 타입의 Value를 가집니다. 아래는 위에서 제시한 구조의 Json 데이터 예시입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1663490267326&quot; class=&quot;r&quot; data-ke-language=&quot;r&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;A&quot; :
    [
      {
        &quot;AA&quot; : &quot;Array index 1 and property 1 value&quot;,
        &quot;BB&quot; : &quot;Array index 1 and property 2 value&quot;,
        &quot;CC&quot; : &quot;Array index 1 and property 3 value&quot;
      },
      {
        &quot;AA&quot; : &quot;Array index 2 and property 1 value&quot;,
        &quot;BB&quot; : &quot;Array index 2 and property 2 value&quot;,
        &quot;CC&quot; : &quot;Array index 2 and property 3 value&quot;
      },
      {
        &quot;AA&quot; : &quot;Array index 3 and property 1 value&quot;,
        &quot;BB&quot; : &quot;Array index 3 and property 2 value&quot;,
        &quot;CC&quot; : &quot;Array index 3 and property 3 value&quot;
      }
    ],
  &quot;B&quot; : &quot;String value&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 그리고 NiFi에서는 BB를 key로 가지는 value들을 모두 base64 encoding한 데이터를 사용할 예정입니다. 아래 링크를 이용하면 쉽게 base64 encoding, decoding을 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://www.base64decode.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.base64decode.org/&lt;/a&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1663492571659&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Base64 Decode and Encode - Online&quot; data-og-description=&quot;Decode from Base64 format or encode into it with various advanced options. Our site has an easy to use online tool to convert your data.&quot; data-og-host=&quot;www.base64decode.org&quot; data-og-source-url=&quot;https://www.base64decode.org/&quot; data-og-url=&quot;https://www.base64decode.org/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/g57UC/hyPOSZeGfq/MEQtQhSMmMoXKkF1rQM5xK/img.png?width=600&amp;amp;height=315&amp;amp;face=228_192_257_224&quot;&gt;&lt;a href=&quot;https://www.base64decode.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.base64decode.org/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/g57UC/hyPOSZeGfq/MEQtQhSMmMoXKkF1rQM5xK/img.png?width=600&amp;amp;height=315&amp;amp;face=228_192_257_224');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Base64 Decode and Encode - Online&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Decode from Base64 format or encode into it with various advanced options. Our site has an easy to use online tool to convert your data.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.base64decode.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;pre id=&quot;code_1663492619414&quot; class=&quot;r&quot; data-ke-language=&quot;r&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;A&quot; :
    [
      {
        &quot;AA&quot; : &quot;Array index 1 and property 1 value&quot;,
        &quot;BB&quot; : &quot;QXJyYXkgaW5kZXggMSBhbmQgcHJvcGVydHkgMiB2YWx1ZQ==&quot;,
        &quot;CC&quot; : &quot;Array index 1 and property 3 value&quot;
      },
      {
        &quot;AA&quot; : &quot;Array index 2 and property 1 value&quot;,
        &quot;BB&quot; : &quot;QXJyYXkgaW5kZXggMiBhbmQgcHJvcGVydHkgMiB2YWx1ZQ==&quot;,
        &quot;CC&quot; : &quot;Array index 2 and property 3 value&quot;
      },
      {
        &quot;AA&quot; : &quot;Array index 3 and property 1 value&quot;,
        &quot;BB&quot; : &quot;QXJyYXkgaW5kZXggMyBhbmQgcHJvcGVydHkgMiB2YWx1ZQ==&quot;,
        &quot;CC&quot; : &quot;Array index 3 and property 3 value&quot;
      }
    ],
  &quot;B&quot; : &quot;String value&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;FlowFile 생성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;NiFi에서는 FlowFile을 생성하는 &lt;b&gt;GenerateFlowFile&lt;/b&gt; Procssor가 존재하기 때문에 직접 Json 데이터를 생성 후 NiFi에서 불러 올 필요가 없습니다. 아래와 같이 Processor 생성 후 &quot;Custom Text&quot;에 우리가 원하는 Json 데이터를 넣어줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;1278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lZ1om/btrMoyJxKSM/QIuo7xlcSKwwuxzuBKq2GK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lZ1om/btrMoyJxKSM/QIuo7xlcSKwwuxzuBKq2GK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lZ1om/btrMoyJxKSM/QIuo7xlcSKwwuxzuBKq2GK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlZ1om%2FbtrMoyJxKSM%2FQIuo7xlcSKwwuxzuBKq2GK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;729&quot; height=&quot;553&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;1278&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;ExecuteGroovyScript Processor 사용&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 동적인 크기의 Array를 가진 Json 데이터를 처리하기위해 NiFi의 다양한 Procssor를 사용하며 시도해봤습니다. 하지만 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;대부분의 Procssor들이 동적인 크기의 Array를 처리할 수 없었고, 몇몇 존재하는 JoltTransformJson과 같은 Procssor들은 동적으로 처리를 할 수 있지만, 값들을 base64 decoding 하는데 어려움이 있었습니다.&lt;/span&gt;&lt;/b&gt; 그래서 결국 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;직접 코딩을 한 Script를 사용하여 Json 데이터를 처리하는 것이 가장 적합&lt;/span&gt;&lt;/b&gt;하다고 생각했습니다. 그리고 대량의 데이터를 처리하기 위해서는 속도가 중요한데 Python도 가능했지만 이는 Groovy 언어보다 속도에서 느리다는 정보가 있었고, NiFi에서 Groovy  script를 많이 사용한다는 점을 고려하여 ExecuteGroovyScript를 사용하기로 결정했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;( Script를 사용하지 않고 NiFi의 Procssor만을 사용하여 처리하는 방법에 대해서는 추후에 글을 게시하겠습니다. )&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;993&quot; data-origin-height=&quot;1074&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brdd57/btrMDpffSKb/kAlULk6l7QxSiCEJqEeAMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brdd57/btrMDpffSKb/kAlULk6l7QxSiCEJqEeAMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brdd57/btrMDpffSKb/kAlULk6l7QxSiCEJqEeAMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbrdd57%2FbtrMDpffSKb%2FkAlULk6l7QxSiCEJqEeAMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;729&quot; height=&quot;788&quot; data-origin-width=&quot;993&quot; data-origin-height=&quot;1074&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;ExecuteGroovyScript의 데이터 결과를 확인하기 위한 사용하지 않을 UpdateAttribute Procssor 추가 후 연결해 Success, Failure Queue를 만들어줍니다. ExecuteGroovyScript의 설정 값은 딱히 건드릴 게 없습니다. &quot;Script Body&quot;에 Groovy script 내용을 넣어줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1663494612320&quot; class=&quot;scala&quot; data-ke-language=&quot;scala&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
import org.apache.nifi.processor.io.StreamCallback
import java.nio.charset.StandardCharsets

def flowFile = session.get()
if( flowFile == null ){
    return;
}

def data
def beforeData

try{

    flowFile = session.write(flowFile, {inputStream, outputStream -&amp;gt;
    
        def content = inputStream.getText(&quot;UTF-8&quot;)
 
        beforeData = new JsonSlurper().parseText(content)
        data = new JsonSlurper().parseText(content)

        data.A.each{ obj -&amp;gt;
            if( !obj[&quot;BB&quot;].isEmpty() ) {
                def decodedString = new String(obj[&quot;BB&quot;].decodeBase64())
                obj[&quot;BB&quot;] = decodedString 
            }
        }

        outputStream.write(JsonOutput.toJson(data).getBytes(StandardCharsets.UTF_8))
    } as StreamCallback)

} catch (Exception e){
    flowFile = session.putAttribute(flowFile, &quot;errorMessage&quot;, e.getMessage().toString())
    session.transfer(flowFile, REL_FAILURE)
    return;
}

flowFile = session.putAttribute(flowFile, &quot;afterData&quot;, data.toString())
flowFile = session.putAttribute(flowFile, &quot;beforeData&quot;, beforeData.toString())
session.transfer(flowFile, REL_SUCCESS)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Groovy script 내용&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;우선 NiFi는 실시간 데이터 처리를 위한 소프트웨어이기 때문에 기본적으로 streaming 데이터 처리로 진행됩니다. 그래서 일반적으로 하는 코딩과는 느낌이 조금 다르지만 주어진 코드 내에서 원하는 내용만 작성해주면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1663494944991&quot; class=&quot;scala&quot; data-ke-language=&quot;scala&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import org.apache.nifi.processor.io.StreamCallback

def flowFile = session.get()
if( flowFile == null ){
    return;
}

try{

    flowFile = session.write(flowFile, {inputStream, outputStream -&amp;gt;
    
        // 데이터 처리 내용 작성
        def output
        

        outputStream.write(output)
    } as StreamCallback)

} catch (Exception e){
    session.transfer(flowFile, REL_FAILURE)
    return;
}

session.transfer(flowFile, REL_SUCCESS)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위와 같이 기본적인 템플릿 작성 후에 주석으로 표시된 부분에 데이터를 처리할 내용을 작성해줍니다. FlowFile마다 데이터 처리 내용이 적용이 되고 FlowFile의 content를 사용하기 위해서는 위의 코드 기준으로 &quot;inputStream&quot; 변수를 사용해줍니다. 그럼 이제 Json 데이터를 처리하는 내용을 설명하겠습니다. &lt;b&gt;아래 코드는 위 코드 주석에 해당되는 내용입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1663495176287&quot; class=&quot;scala&quot; data-ke-language=&quot;scala&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;try{

    flowFile = session.write(flowFile, {inputStream, outputStream -&amp;gt;

        // 데이터 처리 내용 작성
        def content = inputStream.getText(&quot;UTF-8&quot;)
 
        beforeData = new JsonSlurper().parseText(content)
        data = new JsonSlurper().parseText(content)

        data.A.each{ obj -&amp;gt;
            if( !obj[&quot;BB&quot;].isEmpty() ) {
                def decodedString = new String(obj[&quot;BB&quot;].decodeBase64())
                obj[&quot;BB&quot;] = decodedString 
            }
        }

        outputStream.write(JsonOutput.toJson(data).getBytes(StandardCharsets.UTF_8))
    } as StreamCallback)

}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;우선 Json 데이터 내용을 inputStream으로부터 불러와 content 변수에 넣어줍니다. String 형태로 받아온 Json 데이터를 파싱하기 위해 JsonSluper의 parseText 함수를 이용해 &quot;data&quot; 변수에 넣어줍니다. 이때 선언한 &quot;beforeData&quot;는 데이터 처리 전,후를 비교하기 위해 만든 변수입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&quot;data&quot; 변수에 Json 데이터를 파싱한 결과를 넣어줬기 때문에, &quot;.&quot;을 이용하여 nested Json 데이터에 접근할 수 있고 Array 타입은 each를 사용하여 loop 형태로 접근하여 각 loop 단계마다 &quot;obj&quot; 변수에 매핑됩니다. &quot;.&quot;과 each문을 사용하여 원하는 하위 데이터까지 접근을 했다면 key / value 자료구조처럼 사용하면 우리가 원하는 데이터를 처리할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;우리가 접근해서 처리하고 싶은 항목은 &quot;BB&quot;이기 때문에 &lt;b&gt;&quot;&lt;span style=&quot;color: #006dd7;&quot;&gt;data.A&quot;에 접근 후 each로 Array 타입 loop를 실행&lt;/span&gt;&lt;/b&gt;합니다. loop 문 안에서는 &quot;obj&quot;에 접근하여 &quot;obj[&quot;BB&quot;]&quot;를 이용하여 &quot;BB&quot; key의 value에 접근합니다. Groovy에서는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&quot;&lt;b&gt;decodeBase64()&quot; 함수를 이용하여 Base64 decoding&lt;/b&gt;&lt;/span&gt;을 할 수 있습니다. Decoding된 데이터를 &lt;span style=&quot;color: #006dd7;&quot;&gt;S&lt;b&gt;tring 형태로 변환하여 다시 &quot;BB&quot; key의 value에 넣어줍니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1663684992583&quot; class=&quot;scala&quot; data-ke-language=&quot;scala&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;catch (Exception e){
    flowFile = session.putAttribute(flowFile, &quot;errorMessage&quot;, e.getMessage().toString())
    session.transfer(flowFile, REL_FAILURE)
    return;
}

flowFile = session.putAttribute(flowFile, &quot;afterData&quot;, data.toString())
flowFile = session.putAttribute(flowFile, &quot;beforeData&quot;, beforeData.toString())
session.transfer(flowFile, REL_SUCCESS)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이어서 나머지 코드도 작성해줍니다. try / catch에 걸려  exception이 발생했다면 에러 메세지를 FlowFile의 attribute에 넣어준다면 원인 파악을 좀 더 쉽게 할 수 있습니다. 그리고 Processor 의 결과는 failure로 처리해줍니다. 데이터 처리가 정상적으로 되었다면 처리 전,후를 비교하기 위해 &quot;data&quot;와 &quot;beforedata&quot; 변수를 attribute에 넣어준다면 쉽게 확인할 수 있습니다. 마찬가지로 Processor의 결과는 success로 처리해줍니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결과 확인&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;GenerateFlowFile 실행&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1063&quot; data-origin-height=&quot;698&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TqdRE/btrMEtugRkp/3bGd3JcXOWZUOrdqcMVgUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TqdRE/btrMEtugRkp/3bGd3JcXOWZUOrdqcMVgUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TqdRE/btrMEtugRkp/3bGd3JcXOWZUOrdqcMVgUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTqdRE%2FbtrMEtugRkp%2F3bGd3JcXOWZUOrdqcMVgUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;670&quot; height=&quot;440&quot; data-origin-width=&quot;1063&quot; data-origin-height=&quot;698&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ExecuteGroovyScript 실행&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;704&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdhBiu/btrMDRWD9IX/OyWtNwICKAo6cPKkWebUR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdhBiu/btrMDRWD9IX/OyWtNwICKAo6cPKkWebUR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdhBiu/btrMDRWD9IX/OyWtNwICKAo6cPKkWebUR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdhBiu%2FbtrMDRWD9IX%2FOyWtNwICKAo6cPKkWebUR0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;668&quot; height=&quot;421&quot; data-origin-width=&quot;1116&quot; data-origin-height=&quot;704&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;FlowFile 결과&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;637&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bO1ULV/btrMDFaVW78/0Jvg1HFUxwUR0pkmgph8F1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bO1ULV/btrMDFaVW78/0Jvg1HFUxwUR0pkmgph8F1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bO1ULV/btrMDFaVW78/0Jvg1HFUxwUR0pkmgph8F1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbO1ULV%2FbtrMDFaVW78%2F0Jvg1HFUxwUR0pkmgph8F1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;537&quot; height=&quot;395&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;637&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;710&quot; data-origin-height=&quot;449&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNeckO/btrMDn2L6LM/yu4UDFyacY9FCGhFwM3xDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNeckO/btrMDn2L6LM/yu4UDFyacY9FCGhFwM3xDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNeckO/btrMDn2L6LM/yu4UDFyacY9FCGhFwM3xDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNeckO%2FbtrMDn2L6LM%2Fyu4UDFyacY9FCGhFwM3xDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;568&quot; height=&quot;359&quot; data-origin-width=&quot;710&quot; data-origin-height=&quot;449&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Hadoop Ecosystem/NiFi</category>
      <category>base64</category>
      <category>data</category>
      <category>decoding</category>
      <category>Encoding</category>
      <category>json</category>
      <category>NiFi</category>
      <author>Taaewoo</author>
      <guid isPermaLink="true">https://taaewoo.tistory.com/68</guid>
      <comments>https://taaewoo.tistory.com/68#entry68comment</comments>
      <pubDate>Wed, 21 Sep 2022 00:09:08 +0900</pubDate>
    </item>
  </channel>
</rss>