<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>de_mini.log</title>
        <link>https://velog.io/</link>
        <description>주니어 데이터엔지니어</description>
        <lastBuildDate>Wed, 26 Apr 2023 02:13:02 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. de_mini.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/de_mini" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[JPA 공부]]></title>
            <link>https://velog.io/@de_mini/JPA-%EA%B3%B5%EB%B6%80</link>
            <guid>https://velog.io/@de_mini/JPA-%EA%B3%B5%EB%B6%80</guid>
            <pubDate>Wed, 26 Apr 2023 02:13:02 GMT</pubDate>
            <description><![CDATA[<h1 id="1-jpa란">1. JPA란</h1>
<p>JPA 는 Java Persistence(영속성) API 입니다.
여기서 Persistence란, 사전적 의미로 &quot;영속성&quot;을 의미하며, 데이터가  (없어지지 않고 오랜동안) 지속됨을 의미합니다.</p>
<blockquote>
<ul>
<li>램은 휘발성 데이터를 저장 - 컴퓨터가 꺼지면 사라짐</li>
</ul>
</blockquote>
<ul>
<li>데이터가 날라가지 않도록 -&gt; 하드디스크에 저장하면 안 사라짐</li>
<li>=&gt; 이게 퍼시스턴스(영구히 기록)</li>
</ul>
<p>다시 JPA란,
Java Persitance API 는 &quot;자바에서 데이터를 영구히 기록할 수 있는(DBMS에) 환경을 제공하는 API&quot; 라고 말할 수 있다.</p>
<h4 id="여기서-api는">여기서 API는,</h4>
<blockquote>
<p>애플리케이션(Apllication) -&gt; 프로그램
프로그래밍(Programming) -&gt; 프로그래밍
인터페이스(Interface) -&gt; 인터페이스</p>
</blockquote>
<h4 id="--인터페이스를-통해-프로그래밍하여-프로그램을-만듬">-&gt; 인터페이스를 통해 프로그래밍하여 프로그램을 만듬</h4>
<p>API란 &quot;인터페이스(어떤 약속)을 토대로 요청에 대한 응답을 제공해주는 프로그램&quot;정도로 이해할 수 있다.</p>
<p>다시다시 JPA를 풀어서 설명하면..!!</p>
<blockquote>
<ul>
<li>JAVA </li>
</ul>
</blockquote>
<ul>
<li>Persistence</li>
<li>Application Programming Interface 
자바 프로그램을할 때 영구적으로 데이터를 저장하기위해 필요한 인테페이스를 제공해주는 것</li>
</ul>
<h1 id="2-orm이란">2. ORM이란</h1>
<p>JPA는 ORM 기술입니다.</p>
<p><strong>ORM(Object Relational Mapping)</strong>이란,</p>
<p>객체를(Object)와 데이터베이스의 데이터를 연결해주는(매핑) 기술이다.</p>
<p>쉽게 말하자면, ORM의 역할을 설명하면서 이해할 수 있다.</p>
<p>DB 데이터와 JAVA에서의 데이터 타입이 다르기 때문에, DB의 데이터를 JAVA에서 사용하기 위해서, Object를 만들어야하는데, 이를 모델링이라고 한다.</p>
<blockquote>
</blockquote>
<h3 id="코드와-실제-데이터의-매핑">[코드와 실제 데이터의 매핑]</h3>
<p><img src="https://velog.velcdn.com/images/de_mini/post/bc3da299-2d6a-4df5-a67b-56e279e380de/image.png" alt=""></p>
<p>ORM 없이 DataBase의 데이터를 조작하기 위해서는 아래의 일련의 과정을 통해야한다.</p>
<blockquote>
</blockquote>
<h3 id="db-데이터-생성-과정">[DB 데이터 생성 과정]</h3>
<p><img src="https://velog.velcdn.com/images/de_mini/post/ad8bc415-81da-4ca6-89c6-e10c3b0f6ce2/image.png" alt=""></p>
<p>   이런 일련의 작업(CRUD)를 ORM에서 자동으로 제공해준다!!</p>
<h1 id="3-jpa의-구조">3. JPA의 구조</h1>
<p>JPA는 특정기능을 제공하는 라이브러리가 아닌, 인터페이스입니다.</p>
<p>그저 인터페이스이기 때문에 Hibernate, OpenJPA 등이 JPA를 구현합니다.</p>
<p><img src="https://velog.velcdn.com/images/de_mini/post/0c312fda-d6f1-4291-a395-f3001fe94ec7/image.png" alt=""></p>
<p>하이버네이트 외에도 EclipseLink, DataNucleus, OpenJPA, TopLink Essentials 등이 있습니다.</p>
<p>하이버네이트는 JPA 구현체의 한 종류입니다</p>
<p>하이버네이트 ORM(Hibernate ORM)은, 자바 언어를 위한 객체 관계 매핑 프레임워크로, 객체 지향 도메인 모델을 관계형 데이터베이스로 매핑하기 위한 프레임워크를 제공합니다.</p>
<p>JPA는 DB와 자바 객체를 매핑하기 위한 인터페이스(API)를 제공하고 JPA 구현체(하이버네이트)는 이 인터페이스를 구현한 것입니다.</p>
<p>하이버네이트 외에도 EclipseLink, DataNucleus, OpenJPA, TopLink Essentials 등이 있습니다.</p>
<h1 id="4-jpa-vs-spring-data-jpa">4. JPA vs Spring Data JPA</h1>
<p>JPA와 Spring Data JPA는 다르다.</p>
<p>그럼 스프링부트에서 사용하는 JPA가 지금까지 말해왔던 JPA일까요?</p>
<p>아닙니다. 스프링부트에서 사용하는 JPA는 Spring Data JPA로, JPA를 더 쉽게 사용하기 위해 스프링에서 제공하고 있는 프레임워크 입니다.</p>
<p><img src="https://velog.velcdn.com/images/de_mini/post/8712e90a-8f13-449a-b9a6-29323071d911/image.png" alt=""></p>
<p>JPA 클래스 관계</p>
<p>JPA와 Hibernate는 마치 자바의 interface와 해당 interface를 구현한 class와 같은 관계이다.
<img src="https://velog.velcdn.com/images/de_mini/post/a8ba934f-f3af-446e-9071-2c44d49adcd1/image.png" alt=""></p>
<blockquote>
<p>위 사진은 JPA와 Hibernate의 상속 및 구현 관계를 나타낸 것이다.</p>
</blockquote>
<p>JPA의 핵심은  ** EntityManagerFactory,  EntityManager, EnttyTransaction** 이며,  </p>
<blockquote>
</blockquote>
<p>Hibernate에서는 각각 SessionFactory, Session, Transaction으로 상속받고 각각 Impl로 구현하고 있음을 확인할 수 있다.</p>
<blockquote>
</blockquote>
<p>Spring으로 개발을 하면서, EntityManager를 직접 사용할일은 거의 없었다. </p>
<blockquote>
</blockquote>
<p>*<em>Spring 부트에서 DB에 접근하기위해 사용할 때는 Repository를 사용했고, 이 레포지토리가 Spring Data JPA의 핵심이라고 한다, *</em></p>
<p>Spring Data JPA는 Spring에서 제공하는 모듈 중 하나로, 개발자가 JPA를 더 쉽고 편하게 사용할 수 있도록 도와준다.</p>
<p>이는 <strong>JPA를 한 단계 추상화시킨 Repository라는 인터페이스를 제공함으로써 이루어진다.</strong></p>
<p>사용자가 Repository 인터페이스에 정해진 규칙대로 메소드를 입력하면, Spring이 알아서 해당 메소드 이름에 적합한 쿼리를 날리는 구현체를 만들어서 Bean으로 등록해준다.</p>
<h4 id="spring-data-jpa가-jpa를-추상화했다는-말은-spring-data-jpa의-repository의-구현에서-jpa를-사용하고-있다는-것이다">&quot;Spring Data JPA가 JPA를 추상화했다&quot;는 말은, Spring Data JPA의 Repository의 구현에서 JPA를 사용하고 있다는 것이다.</h4>
<h2 id="spring-jpa-data-doc에서는">Spring JPA Data Doc에서는?</h2>
<p>Spring Data JPA에서는 Repository에서 JPA 인터페이스를 상속받아 아래와 같은 키워드만 있으면</p>
<p>JPA를 통해서 SQL이 자동 생성되어 사용할 수 있습니다.</p>
<p>Keyword|Sample|snippet
|---|---|---|
<code>And</code> |findByLastnameAndFirstname|… where x.lastname = ?1 and x.firstname = ?2
<code>Or</code>|findByLastnameOrFirstname|… where x.lastname = ?1 or x.firstname = ?2
<code>Is, Equals</code>|findByFirstname,findByFirstnameIs,findByFirstnameEquals|… where x.firstname = ?1
<code>Between</code>|findByStartDateBetween|… where x.startDate between ?1 and ?2
<code>LessThan</code>|findByAgeLessThan|… where x.age &lt; ?1
<code>LessThanEqual</code>|findByAgeLessThanEqual|… where x.age &lt;= ?1
<code>GreaterThan</code>|findByAgeGreaterThan|… where x.age &gt; ?1
<code>GreaterThanEqual</code>|findByAgeGreaterThanEqual|… where x.age &gt;= ?1
<code>After</code>|findByStartDateAfter|… where x.startDate &gt; ?1
<code>Before</code>|findByStartDateBefore|… where x.startDate &lt; ?1
<code>IsNull, Null</code>|findByAge(Is)Null|… where x.age is null
<code>IsNotNull, NotNull</code>|findByAge(Is)NotNull|… where x.age not null
<code>Like</code>|findByFirstnameLike|… where x.firstname like ?1
<code>NotLike</code>|findByFirstnameNotLike|… where x.firstname not like ?1
<code>StartingWith</code>|findByFirstnameStartingWith|… where x.firstname like ?1 (parameter bound with appended %)
<code>EndingWith</code>|findByFirstnameEndingWith|… where x.firstname like ?1 (parameter bound with prepended %)
<code>Containing</code>|findByFirstnameContaining|… where x.firstname like ?1 (parameter bound wrapped in %)
<code>OrderBy</code>|findByAgeOrderByLastnameDesc|… where x.age = ?1 order by x.lastname desc
<code>Not</code>|findByLastnameNot|… where x.lastname &lt;&gt; ?1
<code>In</code>|findByAgeIn(Collection&lt;Age&gt; ages)|… where x.age in ?1
<code>NotIn</code>|findByAgeNotIn(Collection&lt;Age&gt; ages)|… where x.age not in ?1
<code>TRUE</code>|findByActiveTrue()|… where x.active = true
<code>FALSE</code>|findByActiveFalse()|… where x.active = false
<code>IgnoreCase</code>|findByFirstnameIgnoreCase|… where UPPER(x.firstame) = UPPER(?1)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Sqoop 명령어 옵션 모음]]></title>
            <link>https://velog.io/@de_mini/sqoopoption</link>
            <guid>https://velog.io/@de_mini/sqoopoption</guid>
            <pubDate>Fri, 30 Dec 2022 02:23:36 GMT</pubDate>
            <description><![CDATA[<p>참고 : <a href="https://sqoop.apache.org/docs/1.4.7/SqoopUserGuide.html">https://sqoop.apache.org/docs/1.4.7/SqoopUserGuide.html</a></p>
<h1 id="0-sqoop-help">0. sqoop-help</h1>
<p>Sqoop에는 도움말 도구가 포함되어있습니다. 
사용 가능한 모든 도구 목록을 표시하려면 다음 명령을 사용합니다.</p>
<blockquote>
</blockquote>
<p>$ sqoop help
usage: sqoop COMMAND [ARGS]</p>
<blockquote>
<table>
<thead>
<tr>
<th>인수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>codegen</code></td>
<td>데이터베이스 레코드를 가져와 캡슐화하고 해석하는 Java 클래스를 생성함 (Table Schema 구조를 기반으로 DAO 클래스를 자동으로 생성함)</td>
</tr>
<tr>
<td><code>create-hive-table</code></td>
<td>RDBMS의 table을 기반으로 Hive에 table을 생성합니다.</td>
</tr>
<tr>
<td><code>eval</code></td>
<td>RDBMS에 SQL 쿼리를 사용하여 콘솔에 결과 표시</td>
</tr>
<tr>
<td><code>export</code></td>
<td>HDFS에서 RDBMS로 데이터를 내보낼 수 있습니다. (대상 테이블은 데이터베이스에 이미 존재해야 합니다.)</td>
</tr>
<tr>
<td><code>help</code></td>
<td>사용 가능한 옵션을 나열합니다.</td>
</tr>
<tr>
<td><code>import</code></td>
<td>RDBMS에서 HDFS로 테이블 가져옵니다.</td>
</tr>
<tr>
<td><code>import-all-tables</code></td>
<td>RDBMS에서 HDFS로 테이블들을 가져옵니다.</td>
</tr>
<tr>
<td><code>import-mainframe</code></td>
<td>메인프레임 서버에서 HDFS로 데이터셋 가져오기</td>
</tr>
<tr>
<td><code>job</code></td>
<td>job 생성 및 저장된 job 실행</td>
</tr>
<tr>
<td><code>list-databases</code></td>
<td>서버에서 사용 가능한 데이터베이스 리스트를 나열합니다.</td>
</tr>
<tr>
<td><code>list-tables</code></td>
<td>데이터베이스에서 사용 가능한 테이블 리스트를 나열합니다.</td>
</tr>
<tr>
<td><code>merge</code></td>
<td>오래된 dataset과 새로운 dataset을 유일 key를 기준으로 병합하여 하나의 dataset으로 만듭니다. (공통된 key의 행이 병합될때 새로운 dataset의 행이 우선적으로 사용됩니다.)</td>
</tr>
<tr>
<td><code>metastore</code></td>
<td>metastore 명령어는 Sqoop이 공유된 메타데이터 저장소를 호스팅할 수 있도록 구성한다. 다수의 사용자와 (또는) 원격 사용자들은 이 메타스토어 내에 정의되는 (sqoop job으로 생성된) 저장된 잡을 정의하고 실행할 수 있다.</td>
</tr>
<tr>
<td><code>version</code></td>
<td>버전 정보 표시</td>
</tr>
</tbody></table>
</blockquote>
<h1 id="1-sqoop-import">1. sqoop-import</h1>
<p>import는 개별 테이블을 RDBMS에서 HDFS로 Import합니다. 테이블의 각 행은 HDFS에서 개별 레코드로 표시됩니다.레코드는 텍스트 파일(한 줄에 1개 레코드)로 저장하거나 Avro 또는 SequenceFiles로 이진 표현으로 저장할 수 있습니다. (Apache Avro는 Json 형태의 스키마를 나타낸다고 한다. 추후에 알아볼 것.)</p>
<blockquote>
</blockquote>
<h3 id="표1-common-argument">표1. Common argument</h3>
<p>$ sqoop import --help</p>
<blockquote>
</blockquote>
<table>
<thead>
<tr>
<th>인수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>--connect &lt;jdbc-url&gt;</code></td>
<td>JDBC URL 지정</td>
</tr>
<tr>
<td><code>--connection-manager &lt;class-name&gt;</code></td>
<td>사용할 connection-manager 클래스 지정 (예시 : --connection-manager org.apache.sqoop.manager.MySQLManager)</td>
</tr>
<tr>
<td><code>--driver &lt;class-name&gt;</code></td>
<td>사용할 JDBC 드라이버 클래스를 수동으로 지정 (예시 : --driver com.mysql.jdbc.Driver)</td>
</tr>
<tr>
<td><code>--hadoop-mapred-home &lt;dir&gt;</code></td>
<td>$HADOOP_MAPRED_HOME 재지정 (해당 path는 맵리듀스 home path)</td>
</tr>
<tr>
<td><code>--help</code></td>
<td>도움말</td>
</tr>
<tr>
<td><code>--P</code></td>
<td>콘솔에서 비밀번호 읽기</td>
</tr>
<tr>
<td><code>--password &lt;password&gt;</code></td>
<td>인증 패스워드 설정</td>
</tr>
<tr>
<td><code>--username &lt;username&gt;</code></td>
<td>인증 사용자 이름 설정</td>
</tr>
<tr>
<td><code>--verbose</code></td>
<td>작업하는 동안 더 많은 정보를 출력할때 사용</td>
</tr>
</tbody></table>
<blockquote>
</blockquote>
<h3 id="표2-import-control-arguments">표2. Import control arguments</h3>
<table>
<thead>
<tr>
<th>인수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>--append</code></td>
<td>HDFS의 기존 Dataset에 데이터 추가</td>
</tr>
<tr>
<td><code>--as-avrodatafile</code></td>
<td>데이터를  Avro data file로  가져오기</td>
</tr>
<tr>
<td><code>--as-sequencefile</code></td>
<td>데이터를 SequenceFiles로 가져옵니다.</td>
</tr>
<tr>
<td><code>--as-textfile</code></td>
<td>데이터를 일반 텍스트로 가져옵니다(기본값).</td>
</tr>
<tr>
<td><code>--as-parquetfile</code></td>
<td>데이터를 Parquet 파일로 가져오기</td>
</tr>
<tr>
<td><code>--boundary-query &lt;statement&gt;</code></td>
<td>분할 생성에 사용할 경계 쿼리 (mapper 개수에 따라서 쿼리가 분할하여 실행됨, index 1 ~ 200 값을 조회하고 매퍼가 4개라면 1<del>50, 51</del>100, 101<del>150, 101</del>200으로 나눠서 실행된다)</td>
</tr>
<tr>
<td><code>--columns &lt;col,col,col?&gt;</code></td>
<td>테이블에서 가져올 속성</td>
</tr>
<tr>
<td><code>--delete-target-dir</code></td>
<td>Import 대상 디렉토리가 있는 경우 삭제</td>
</tr>
<tr>
<td><code>--direct</code></td>
<td>데이터베이스의 Native Tool을 사용하여 보다 빠르게 데이터를 가져올 수 있습니다. (mysqldump 등)</td>
</tr>
<tr>
<td><code>--fetch-size &lt;n&gt;</code></td>
<td>데이터베이스에서 한 번에 읽을 항목 수입니다.</td>
</tr>
<tr>
<td><code>--inline-lob-limit &lt;n&gt;</code></td>
<td>인라인 LOB의 최대 크기 설정 (LOB: 구조화 되지 않은 데이터)</td>
</tr>
<tr>
<td><code>-m,--num-mappers &lt;n&gt;</code></td>
<td>n개의 맵 작업을 사용하여 병렬로 가져오기</td>
</tr>
<tr>
<td><code>-e,--query &lt;statement&gt;</code></td>
<td>쿼리 결과를 Import 합니다. (예시 : -e &quot;select ~&quot;)</td>
</tr>
<tr>
<td><code>--split-by &lt;column-name&gt;</code></td>
<td>작업 단위를 분할하는 데 사용되는 테이블의 열입니다. --autoreset-to-one-mapper 옵션 과 함께 사용할 수 없습니다. (--boundary-query와 달리 데이터를 균일하게 분할합니다.)</td>
</tr>
<tr>
<td><code>--autoreset-to-one-mapper</code></td>
<td>테이블에 기본 키가 없을 때 분할할 열이 제공되기 힘들 경우하나의 매퍼를 사용해야 합니다. --split-by 옵션 과 함께 사용할 수 없습니다 .</td>
</tr>
<tr>
<td><code>--table &lt;table-name&gt;</code></td>
<td>import 테이블</td>
</tr>
<tr>
<td><code>--target-dir &lt;dir&gt;</code></td>
<td>import 결과를 저장하는 HDFS dir (단일 테이블을 가져올때 사용한다.  저장경로 : /user/root/table)</td>
</tr>
<tr>
<td><code>--warehouse-dir &lt;dir&gt;</code></td>
<td>저장할 상위 HDFS dir을 지정할 수 있다. (여러 테이블을 가져올때 상위 디렉토리명을 지정하기 위해 이 옵션을 사용한다. 저장경로 : /user/root/warehouse_dir/table)</td>
</tr>
<tr>
<td><code>--where &lt;where clause&gt;</code></td>
<td>import 할때 사용할 WHERE 절</td>
</tr>
<tr>
<td><code>-z,--compress</code></td>
<td>gzip으로 데이터 압축</td>
</tr>
<tr>
<td><code>--compression-codec &lt;c&gt;</code></td>
<td>Hadoop 압축 코덱 지정 (기본 gzip, SequenceFile, text, Avro file 등으로 지정가능)</td>
</tr>
<tr>
<td><code>--null-string &lt;null-string&gt;</code></td>
<td>문자열 열의 null 값에 쓸 문자열입니다. (표4. Hive arguments TIP2 참고)</td>
</tr>
<tr>
<td><code>--null-non-string &lt;null-string&gt;</code></td>
<td>문자열이 아닌 열의 null 값에 쓸 문자열입니다. (표4 Hive arguments TIP2 참고)</td>
</tr>
<tr>
<td>### 표3. Incremental Imports</td>
<td></td>
</tr>
<tr>
<td>계속 전체 데이터를 가져오면 비효율적이기 때문에 이전에 import한 이후로 변경된 부분만 가져오고 싶을 때 사용합니다.</td>
<td></td>
</tr>
</tbody></table>
<blockquote>
</blockquote>
<table>
<thead>
<tr>
<th>인수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>--check-column (col)</code></td>
<td>가져올 행을 결정할 때 검사할 열을 지정합니다. (열이 CHAR/NCHAR/VARCHAR/VARNCHAR/LONGVARCHAR/LONGNVARCHAR 유형이 아니어야 함)</td>
</tr>
<tr>
<td><code>--incremental (mode)</code></td>
<td>Sqoop이 새 행을 결정하는 방법을 지정합니다. mode는 lastmodified와 append가 있으며 last_value는 check_column을 시간으로 두어 그 시간 이후 에 새로 등록된 데이터를 가져오게됩니다. append는 check_column에서 지정한 열을 기준으로 last-value보다 큰 row들을 가져오게 됩니다.</td>
</tr>
<tr>
<td><code>--last-value (value)</code></td>
<td>last_value값 보다 큰 row들을 import 합니다.</td>
</tr>
<tr>
<td>쿼리 1.  incremental의 mode가 lastmodified일 경우</td>
<td></td>
</tr>
<tr>
<td><code>sqoop import --table tablename --connect jdbc:mysql://dbhost/loudacre --username id --password p --incremental lastmodified --check-column mod_df --last-value ‘2015-09-30 16:00:00’</code></td>
<td></td>
</tr>
<tr>
<td>쿼리 2.  incremental의 mode가 append일 경우</td>
<td></td>
</tr>
<tr>
<td><code>sqoop import --table tablename --connect jdbc:mysql://dbhost/loudacre --username id --pasword p --incremental  append --check-column  id --last-value ‘100&#39;</code></td>
<td></td>
</tr>
<tr>
<td>### 표4. Hive arguments</td>
<td></td>
</tr>
</tbody></table>
<blockquote>
</blockquote>
<p>TIP1. Hive는 이스케이프 문자를 지원하지만, 개행 문자 이스케이프는 처리하지 않습니다. 또한, 필드 구분 기호를 포함할 수 있는 문자를 둘러싸는 개념을 지원하지 않습니다. 따라서 하이브로 작업할 때 문자를 이스케이프하거나 둘러싸는 도움 없이 명확한 필드 및 레코드 종료 구분 기호를 선택하는 것이 좋습니다. 이는 하이브의 입력 구문 분석 기능의 한계 때문입니다.</p>
<blockquote>
</blockquote>
<p>TIP2. Sqoop은 기본적으로 NULL 값을 문자열 null로 가져옵니다. 그러나 Hive는 NULL 값을 나타내기 위해 \N 문자열을 사용하고 있으므로 NULL(IS NULL과 같은)을 처리하는 술어가 올바르게 작동하지 않습니다. NULL 값을 올바르게 보존하려면 가져오기 작업의 경우 매개 변수 --null-string 및 --null-non-string을 추가하고 내보내기 작업의 경우 --input-null-string 및 --input-null-non-string을 추가해야 합니다. sqoop은 생성된 코드에서 이러한 매개 변수를 사용하므로 값 \N에서 \\N으로 적절하게 이스케이프해야 합니다.</p>
<blockquote>
</blockquote>
<table>
<thead>
<tr>
<th>인수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>--hive-home &lt;dir&gt;</code></td>
<td>$HIVE_HOME 오버라이드</td>
</tr>
<tr>
<td><code>--hive-import</code></td>
<td>RDBMS 테이블을 하이브로 가져옵니다 (설정되지 않은 경우 하이브의 기본 구분 기호 사용).</td>
</tr>
<tr>
<td><code>--hive-overwrite</code></td>
<td>하이브 테이블의 기존 데이터를 덮어씁니다.</td>
</tr>
<tr>
<td><code>--create-hive-table</code></td>
<td>기존 RDBMS 테이블을 기반으로 hive 테이블을 생성합니다. 이 옵션이 설정된 경우 생성할 테이블명이 존재할 경우 작업을 실패합니다.</td>
</tr>
<tr>
<td><code>--hive-database &lt;table-name&gt;</code></td>
<td>하이브로 데이터를 가져올 때 사용할 데이터베이스 이름을 설정합니다.</td>
</tr>
<tr>
<td><code>--hive-table &lt;table-name&gt;</code></td>
<td>하이브로 데이터를 가져올 때 사용할 테이블 이름을 설정합니다.</td>
</tr>
<tr>
<td><code>--hive-drop-import-delims</code></td>
<td>하이브로 데이터를 가져올 때 문자열 필드에서 \n, \r 및 \01을 삭제합니다.</td>
</tr>
<tr>
<td><code>--hive-delims-replacement</code></td>
<td>하이브로 데이터를 가져올 때 문자열 필드의 \n, \r 및 \01을 사용자 정의 문자열로 바꿉니다.</td>
</tr>
<tr>
<td><code>--hive-partition-key</code></td>
<td>파티션을 나눌 때 사용할 Hive 필드명</td>
</tr>
<tr>
<td><code>--hive-partition-value &lt;v&gt;</code></td>
<td>Hive로 가져올 때 파티션 키로 사용되는 문자열 값.</td>
</tr>
<tr>
<td><code>--map-column-hive &lt;map&gt;</code></td>
<td>설정된 컬럼들에 대하여 SQL타입에서 Hive타입으로 매핑하는 기본값을 덮어쓴다.</td>
</tr>
</tbody></table>
<h1 id="2-sqoop-export">2. sqoop-export</h1>
<p>export 명령어는 HDFS에서 RDBMS로 데이터를 내보냅니다. 대상 테이블이 데이터베이스에 이미 존재해야 합니다.</p>
<blockquote>
</blockquote>
<h3 id="표1-common-argument-1">표1. Common argument</h3>
<p>$ sqoop export --help</p>
<blockquote>
</blockquote>
<table>
<thead>
<tr>
<th>인수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>--connect &lt;jdbc-url&gt;</code></td>
<td>JDBC 연결 문자열 지정</td>
</tr>
<tr>
<td><code>--connection-manager &lt;class-name&gt;</code></td>
<td>사용할 연결 관리자 클래스 지정</td>
</tr>
<tr>
<td><code>--driver &lt;class-name&gt;</code></td>
<td>사용할 JDBC 드라이버 클래스를 수동으로 지정</td>
</tr>
<tr>
<td><code>--hadoop-mapred-home &lt;dir&gt;</code></td>
<td>$HADOOP_MAPRED_HOME 재지정</td>
</tr>
<tr>
<td><code>--help</code></td>
<td>도움말</td>
</tr>
<tr>
<td><code>--P</code></td>
<td>콘솔에서 비밀번호 읽기</td>
</tr>
<tr>
<td><code>--password &lt;password&gt;</code></td>
<td>인증 패스워드 설정</td>
</tr>
<tr>
<td><code>--username &lt;username&gt;</code></td>
<td>인증 사용자 이름 설정</td>
</tr>
<tr>
<td><code>--verbose</code></td>
<td>작업하는 동안 더 많은 정보를 출력할때 사용</td>
</tr>
</tbody></table>
<blockquote>
</blockquote>
<h3 id="표2-export-control-arguments">표2. Export control arguments</h3>
<table>
<thead>
<tr>
<th>인수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>--columns &lt;col,col,col…&gt;</code></td>
<td>테이블로 export 할 칼럼</td>
</tr>
<tr>
<td><code>--direct</code></td>
<td>mapper나 reducer를 실행하지 않아 빠르게 가져올 수 있음</td>
</tr>
<tr>
<td><code>--export-dir &lt;dir&gt;</code></td>
<td>export 할 HDFS 소스 경로</td>
</tr>
<tr>
<td><code>-m,--num-mappers &lt;n&gt;</code></td>
<td>n개의 맵 작업을 사용하여 병렬로 내보내기</td>
</tr>
<tr>
<td><code>--table &lt;table-name&gt;</code></td>
<td>데이터베이스에 데이터를 채울 테이블명</td>
</tr>
<tr>
<td><code>--call &lt;stored-proc-name&gt;</code></td>
<td>호출할 저장 프로시저</td>
</tr>
<tr>
<td><code>--update-key &lt;col-name&gt;</code></td>
<td>업데이트 key 지정</td>
</tr>
<tr>
<td><code>--update-mode &lt;mode&gt;</code></td>
<td>데이터베이스에서 새 행들이 매칭되지 않는 키로 발견이 되었을 때 어떻게 갱신이 수행되는지를 명시한다.</td>
</tr>
<tr>
<td><code></code></td>
<td>mode는 updataeonly (update), allowinsert(update + 존재하지 않는 key 발견시 insert)가 있습니다.</td>
</tr>
<tr>
<td><code>--input-null-string &lt;null-string&gt;</code></td>
<td>문자열 열에 대해 null로 해석할 문자열</td>
</tr>
<tr>
<td><code>--input-null-non-string &lt;null-string&gt;</code></td>
<td>문자열이 아닌 열에 대해 null로 해석할 문자열</td>
</tr>
<tr>
<td><code>--staging-table &lt;staging-table-name&gt;</code></td>
<td>최종 테이블에 삽입되기 전에 데이터가 스테이징될 테이블입니다. 해당 테이블에 데이터가 존재한다면 --clear-staging-table 옵션을 사용해 테이블을 비워야 합니다. (export 작업이 실패하면 부분 데이터가 데이터베이스에 커밋되는 등 삽입 충돌이 발생할 위험성 때문에 보조 테이블을 쓴다.)</td>
</tr>
<tr>
<td><code>--clear-staging-table</code></td>
<td>export 하기 전 staging-table에 있는 기존데이터들을 삭제합니다.</td>
</tr>
<tr>
<td><code>--batch</code></td>
<td>JDBC 드라이버를 통하여 batch mode 사용</td>
</tr>
</tbody></table>
<h1 id="3-sqoop-eval">3. sqoop-eval</h1>
<p>sqoop-eval를 사용하면 데이터베이스에 대해 간단한 SQL 쿼리를 빠르게 실행할 수 있습니다. 쿼리 결과는 콘솔에 출력됩니다. 이를 통해 사용자는 import 쿼리를 미리 사용해보고 예상 데이터를 가져왔는지 확인할 수 있습니다.
<code>$ sqoop eval --connect jdbc:mysql://db.example.com/corp --query &quot;SELECT * FROM Employees LIMIT 10&quot;</code></p>
<h1 id="4-sqoop-job">4. sqoop-job</h1>
<p>job 명령어는 저장된 job을 생성하고 이용할 수 있도록 한다. 저장된 job은 job을 등록할때 사용한 매개변수들을 기억한다. 그 잡을 작동시킴으로써 재실행될 수 있다.
(반복해서 사용할 sqoop 명령어가 있을때 job 생성 및 사용)</p>
<p>저장된 잡이 Incremental Import를 수행하는 데에 구성된다면, 지속적으로 가장 최근의 행들만 가져올 수 있도록 한다.</p>
<blockquote>
</blockquote>
<table>
<thead>
<tr>
<th>인수</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>--create &lt;job-id&gt;</code></td>
<td>명시된 잡 아이디(명)으로 새로운 저장된 잡을 정의합니다. --로 분리된 두번째 Sqoop 명령줄이 명시되어야 하며 이것은 저장된 잡을 정의한다.</td>
</tr>
<tr>
<td><code>--delete &lt;job-id&gt;</code></td>
<td>저장된 job을 삭제합니다.</td>
</tr>
<tr>
<td><code>--exec &lt;job-id&gt;</code></td>
<td>--create로 정의된 job이 주어지면 그 job을 실행합니다.</td>
</tr>
<tr>
<td><code>--show &lt;job-id&gt;</code></td>
<td>저장된 job의 설정을 표시합니다.</td>
</tr>
<tr>
<td><code>--list</code></td>
<td>저장된 모든 job 나열</td>
</tr>
</tbody></table>
<blockquote>
</blockquote>
<p>--create 옵션 예시 (myjob이라는 job을 생성, mysql의 mytable을 import 하는 job)
<code>$ sqoop job --create myjob -- import --connect jdbc:mysql://example.com/db --table mytable</code></p>
<blockquote>
</blockquote>
<p>--show 옵션 예시 (tool, option 확인 후 원하는 기능을 수행한다면 exec명령어를 통해 해당 job을 실행할 수 있음)
<code>$ sqoop job --show myjob</code></p>
<blockquote>
</blockquote>
<p><img src="https://velog.velcdn.com/images/de_mini/post/9fb0e964-2abd-4f1a-b063-9bf4aad92851/image.png" alt=""></p>
<blockquote>
</blockquote>
<p>--exec 옵션 예시 (exec 옵션은 --의 뒤에 인자들을 제공하여 저장된 잡의 인자들을 오버라이드 할 수 있게 한다. 예를 들면, 아래와 같이 사용자명과 비밀번호를 명시할 수 있다.)
<code>$ sqoop job --exec myjob -- --username root -P</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Sqoop (스쿱) 이란?]]></title>
            <link>https://velog.io/@de_mini/sqoop</link>
            <guid>https://velog.io/@de_mini/sqoop</guid>
            <pubDate>Tue, 27 Dec 2022 07:13:44 GMT</pubDate>
            <description><![CDATA[<h1 id="아파치-스쿱apache-sqoop">아파치 스쿱(Apache Sqoop)</h1>
<p>스쿱(Sqoop)은 구조화된 관계형 데이터베이스(RDBMS)와 아파치 하둡간의 대용량 데이터들을 효율적으로 변환해주는 명령 줄 인터페이스(Command-Line Interface) 애플리케이션이다. 
관계형 데이터베이스(Oracle, Mysql, etc..) 데이터를 HDFS, Hive, Hbase에 임포트(import) 하거나, 반대로 관계형 데이터베이스에 데이터를 익스포트(export)할 수 있다.
스쿱은 데이터의 가져오기와 내보내기를 맵리듀스를 통해 처리하여 장애 허용 능력뿐만 아니라 병렬 처리가 가능하게 한다. 
(장애 허용 능력: 정상적으로 작동할 수 없는 상황이 발생하였을 때, 데이터가 분실되거나 진행 중인 작업이 훼손되는 사태가 일어나지 않도록 대응하능 능력)</p>
<p>참고 사이트:
<a href="https://ko.wikipedia.org/wiki/%EC%95%84%ED%8C%8C%EC%B9%98_%EC%8A%A4%EC%BF%B1">https://ko.wikipedia.org/wiki/%EC%95%84%ED%8C%8C%EC%B9%98_%EC%8A%A4%EC%BF%B1</a></p>
<blockquote>
</blockquote>
<h2 id="1-스쿱-아키텍처">1. 스쿱 아키텍처</h2>
<p>스쿱은 관계형 DB를 읽고 쓸 수 있는 커넥터라는 개념을 사용한다. 
커넥터는 각 DB별로 구현돼 있으며, JDBC 드라이버를 이용해 데이터베이스 접속 및 쿼리 실행을 요청한다.
<img src="https://velog.velcdn.com/images/de_mini/post/a5009ba6-2f19-434b-989c-cdfc050c89fa/image.png" alt=""></p>
<h3 id="1-데이터-임포트-동작-방식">1) 데이터 임포트 동작 방식</h3>
<p><img src="https://velog.velcdn.com/images/de_mini/post/341299ad-052c-41c3-bb88-727c076bbc30/image.png" alt=""></p>
<ol>
<li>클라이언트가 스쿱에 임포트를 요청한다. (이때 클라이언트는 데이터베이스 접속 정보, 임포트 대상 테이블, 임포트 질의, 실행할 맵 태스크 개수 등을 설정하여 요청)</li>
<li>스쿱은 데이터베이스에서 해당 테이블의 메타데이터를 조회해 ORM(Object Realational Mapping) 클래스를 생성한다. ORM에서 익스포트 테이블의 튜플과 임포트 테이블의 튜플이 매핑된다. 그 후 맵리듀스 잡 실행에 필요한 직렬화 메서드가 생성된다.</li>
<li>스쿱은 ORM 클래스가 정상적으로 생성되면 맵리듀스 잡 실행을 요청한다.
(리듀스 태스크는 사용하지 않는다. 맵 태스크의 결과를 임포트해 사용한다.)</li>
<li>맵 태스크는 DB에 JDBC로 접속한 후 SELECT 질의를 실행한다.</li>
<li>맵 태스크는 질의문을 실행한 결과를 HDFS에 저장한다. 모든 맵 태스크가 종료되면 스쿱은 클라이언트에게 작업이 정상적으로 종료됐다고 알려준다.
// 6번 부터는 스쿱 import 문에 테이블 생성 코드 추가했다고 가정.</li>
<li>사용자가 설정한 하이브 테이블을 생성한다.</li>
<li>맵 태스크에 저장된 결과를 하이브 테이블의 데이터 경로로 로딩한다.<h3 id="2-데이터-익스포트-동작-방식">2) 데이터 익스포트 동작 방식</h3>
export 작업이 실패하면 일부 데이터가 데이터베이스에 커밋되는 등 삽입 충돌이 발생할 위험성 때문에 중간 테이블을 사용합니다.
<img src="https://velog.velcdn.com/images/de_mini/post/8690289b-bad5-472a-9be8-9f68bd96bf60/image.png" alt=""></li>
<li>클라이언트가 스쿱에 익스포트를 요청한다.</li>
<li>스쿱은 RDBMS에서 메타데이터를 조회 후 맵리듀스 잡에서 사용할 ORM 클래스를 생성한다.</li>
<li>스쿱은 데이터베이스의 중간 테이블의 데이터를 모두 삭제한 후 맵리듀스 잡을 실행한다.</li>
<li>맵 태스크는 HDFS에서 데이터를 조회한 후 INSERT 질의문을 만들어 중간 테이블에 데이터를 입력한다. 이때 질의문은 레코드당 한 번씩 실행하는 것이 아니라 천개 단위의 배치로 실행한다. (중간 테이블 및 배치 단위 옵션은 sqoop.export.records.per.statement 옵션으로 수정가능 )</li>
<li>스쿱은 맵리듀스 잡이 정상적으로 종료되면 중간 테이블의 결과를 최종 테이블에 입력한다.
예를 들어, 중간 테이블이 tmp1, 최종 테이블이 result1이라면 하기 쿼리를 실행한다.
insert into result1 (select * from tmp1)</li>
</ol>
]]></description>
        </item>
    </channel>
</rss>