hadoop15--MR調優, 虛擬列, mysql

表的優化

  1. 在表的優化中, 當數據量較大的時候常用的手段就是拆分表, 大表拆小表, 分區表, 臨時表, 外部表
  2. 小表和大表的join, 要把數據量小的表放在join的左邊, 先進行緩存, 這樣會減少表join的時候內存的消耗量

數據傾斜

數據傾斜產生的原因爲分區之後某一個reduce運算的數據量比較小, 而某一個reduce運行的數據量比較大, 造成兩個reduce處理數據不平等

合理設置map數量

可以影響map的數量的因素

在input文件夾中, 每一個文件就是一個map. input文件的數量, input文件的大小都會影響map的數量, 在mapreduce任務中, 一個切片就是一個map任務, 在Driver中設置如下:

FileInputFormat.setMaxInputSplitSize(job, size);
FileInputFormat.setMinInputSplitSize(job, size);

合理設置reduce數量

設置reduce個數:

hive (default)> set mapreduce.job.reduces;
mapreduce.job.reduces=-1
//默認爲-1, 就是不設置reduce的個數

根據業務自定分區規則

並行執行

並行執行與java多線程的異步和同步概念差不多, 在MR運行任務中, 存在很多的MR任務可以進行執行, 有些MR任務和下一個MR任務存在依賴關係, 但是有些MR任務沒有依賴關係. 例如: 存在依賴關係的MR, 一個MR任務的輸出就是下一個MR任務的輸入. 對於沒有依賴關係的MR任務可以使用並行執行, 在同一時間運行多個MR任務, 這樣在運行的過程中效率就會得到提升.

可以通過以下參數來設置

  1. 開啓並行任務
hive (default)> set hive.exec.parallel;
hive.exec.parallel=false
---------------------------------------
set hive.exec.parallel=true;
  1. 設置多少個任務可以同時運行
hive (default)> set hive.exec.parallel.thread.number;
hive.exec.parallel.thread.number=8
//默認值爲8個任務可以同時執行

嚴格模式

hive中提供有嚴格模式, 爲了防止一些查詢出現不好的影響, 例如笛卡爾積, 在嚴格模式下是不能運行的.

默認的嚴格模式設置:

<property>
    <name>hive.mapred.mode</name>
    <value>nonstrict</value>
    <description>
      The mode in which the Hive operations are being performed. 
      In strict mode, some risky queries are not allowed to run. They include:
        Cartesian Product.
        No partition being picked up for a query.
        Comparing bigints and strings.
        Comparing bigints and doubles.
        Orderby without limit.
    </description>
  </property>
  //默認值爲非嚴格模式 : nonstrict

開啓嚴格模式 : strict

開啓了嚴格模式會對查詢語句進行一些限制:

  1. 對於分區表: 必須存在where語句對分區表中的分區字段進行條件過濾, 否則不允許執行該查詢.
  2. 對於使用order by: 當使用orderby語句時, 必須使用limit進行限定, 由於orderby之後所有的數據都會被分到一個reduce中, 這樣reduce操作的數據量太大, 可能時間過長, 導致卡死, 所以爲了防止出現這種情況, 在orderby的時候必須給定limit限制, 減少reduce處理的數據量
  3. 笛卡爾積查詢: 在多表join中會出現笛卡爾積, 笛卡爾積灰造成內存的加大消耗, 爲了防止這種情況, 禁止使用笛卡爾積查詢, 同時防止誤操作

JVM重用

在hive執行計算任務的時候, 會把執行計劃上傳到YARN集羣中進行提交, 運行MR任務, 每次進行任務的運行的時候都會開啓一個JVM進程運行MR任務, 如果提交任務頻繁過多, 就會造成JVM頻繁的開啓和關閉, 在JVM的開啓和關閉的過程中會造成大量的資源浪費.

在處理小文件的時候, 由於map任務較多, 所以JVM或頻繁的開啓和關閉, 所以對於小文件的處理優化, 主要減少JVM開啓的次數

在mapred-default.xml配置文件中有如下參數:

<property>
  <name>mapreduce.job.jvm.numtasks</name>
  <value>10</value>
  <description>How many tasks to run per jvm. If set to -1, there is
  no limit. 
  </description>
</property>

在hive中臨時設置JVM重用任務的數量

hive (default)> set mapreduce.job.jvm.numtasks;
mapreduce.job.jvm.numtasks=1

推測執行

由於集羣中的資源分配不均等, 或者說每個集羣中節點硬件性能會導致某個任務運行的時間快, 或者某個任務運行時間慢, 或者某個任務運行時直接卡死.

爲了防止某些任務在運行過程中拖慢了整個MR任務的進度, 在運行慢的任務節點上, 開啓相同的任務, 如果時間比原來的任務運行的快, 則直接輸出推測的任務.

注意 : 推測執行分爲map端的推測執行以及reduce端的推測執行

map端

設置開啓map端推測執行的參數:

<property>
  <name>mapreduce.map.speculative</name>
  <value>true</value>
  <description>If true, then multiple instances of some map tasks
               may be executed in parallel.</description>
</property>

在hadoop中默認開啓推測執行, 推測執行不是說一卡死就開啓推測任務, 而是必須要運行到5%以上纔開啓推測執行

在hive中通過set設置

hive (default)> set mapreduce.map.speculative;
mapreduce.map.speculative=true

reduce端

設置開啓reduce端推測執行的參數:

<property>
  <name>mapreduce.reduce.speculative</name>
  <value>true</value>
  <description>If true, then multiple instances of some reduce tasks
               may be executed in parallel.</description>
</property>

在hive中通過set設置

hive (default)> set mapreduce.reduce.speculative;
mapreduce.reduce.speculative=true

執行計劃—查看SQL語句的執行過程

hive中提供可以查看hql語句的執行計劃 , 在執行計劃中會生成抽象語法樹, 在語法樹中會顯示hql語句之間的以來關係以及執行過程. 通過這些執行的過程和以來關係可以對hql語句進行優化

explain + 執行語句
------------------------------------------------
hive (default)> explain select * from emp;
OK
Explain
STAGE DEPENDENCIES:
  Stage-0 is a root stage

STAGE PLANS:
  Stage: Stage-0
    Fetch Operator
      limit: -1
      Processor Tree:
        TableScan
          alias: emp
          Statistics: Num rows: 2 Data size: 653 Basic stats: COMPLETE Column stats: NONE
          Select Operator
            expressions: empno (type: int), ename (type: string), job (type: string), mgr (type: int), edate (type: string), sal (type: double), deptno (type: int)
            outputColumnNames: _col0, _col1, _col2, _col3, _col4, _col5, _col6
            Statistics: Num rows: 2 Data size: 653 Basic stats: COMPLETE Column stats: NONE
            ListSink

Time taken: 0.127 seconds, Fetched: 17 row(s)

一般來說都會把複雜語句簡單化處理, 例如多表的join

虛擬列

虛擬列本身是一個不存在的列, 在數據查詢的時候, 可以通過虛擬列查詢數據的路徑, 以及數據的偏移量, 這兩個都是hive中爲用戶提供的虛擬列進行的查詢

INPUT__FILE__NAME : 數據文件的保存路徑

通過查詢得到文件的保存路徑

select ename, INPUT__FILE__NAME  from emp;
SMITH   hdfs://ns1/user/hive/warehouse/emp/emp.txt
ALLEN   hdfs://ns1/user/hive/warehouse/emp/emp.txt
WARD    hdfs://ns1/user/hive/warehouse/emp/emp.txt
JONES   hdfs://ns1/user/hive/warehouse/emp/emp.txt
MARTIN  hdfs://ns1/user/hive/warehouse/emp/emp.txt
BLAKE   hdfs://ns1/user/hive/warehouse/emp/emp.txt
CLARK   hdfs://ns1/user/hive/warehouse/emp/emp.txt
SCOTT   hdfs://ns1/user/hive/warehouse/emp/emp.txt
KING    hdfs://ns1/user/hive/warehouse/emp/emp.txt
TURNER  hdfs://ns1/user/hive/warehouse/emp/emp.txt
ADAMS   hdfs://ns1/user/hive/warehouse/emp/emp.txt
JAMES   hdfs://ns1/user/hive/warehouse/emp/emp.txt
FORD    hdfs://ns1/user/hive/warehouse/emp/emp.txt
MILLER  hdfs://ns1/user/hive/warehouse/emp/emp.txt

BLOCK__OFFSET__INSIDE__FILE : 得到數據文件的偏移量信息

通過虛擬裏得到數據的偏移量

select ename ,BLOCK__OFFSET__INSIDE__FILE  from emp;
ename   block__offset__inside__file
SMITH   0
ALLEN   44
WARD    97
JONES   149
MARTIN  194
BLAKE   249
CLARK   294
SCOTT   339
KING    385
TURNER  429
ADAMS   480
JAMES   524
FORD    567
MILLER  612

安裝配置mysql

由於hive中默認的元數據保存在derby中只能單用戶訪問hive , 則另一用戶無法訪問, 會出現以下錯誤信息:

Caused by: ERROR XSDB6: Another instance of Derby may have already booted the database /opt/app/apache-hive-1.2.1-bin/metastore_db.

爲了解決以上的問題, 可以把hive的元數據保存在mysql中.

mysql的安裝步驟

  1. 在Linux系統中,可能存在mysql的安裝包, 所以第一步先檢查是否安裝過mysql
[hadoop@hadoop apache-hive-1.2.1-bin]$ rpm -qa | grep -i mysql
mysql-libs-5.1.73-5.el6_6.x86_64

執行該命令可以查看是否安裝mysql

  1. 卸載已有的mysql安裝包
[hadoop@hadoop apache-hive-1.2.1-bin]$ sudo rpm -e --nodeps mysql-libs-5.1.73-5.el6_6.x86_64
[sudo] password for hadoop:  
  1. 查看是否卸載成功
[hadoop@hadoop apache-hive-1.2.1-bin]$ rpm -qa | grep -i mysql  
[hadoop@hadoop apache-hive-1.2.1-bin]$ 
  1. mysql分爲server端和client端
 MySQL-client-5.5.47-1.linux2.6.x86_64.rpm
 MySQL-server-5.5.47-1.linux2.6.x86_64.rpm
  1. 安裝mysql軟件

    通過rpm安裝server

sudo rpm -ivh MySQL-server-5.5.47-1.linux2.6.x86_64.rpm 

​ 通過rpm安裝client

sudo rpm -ivh MySQL-client-5.5.47-1.linux2.6.x86_64.rpm
  1. 查看mysql的運行狀態
sudo service mysql status
  1. 啓動mysql服務
[root@hadoop mysql]# service mysql start
Starting MySQL.. SUCCESS!
  1. 再次查看mysql運行狀態
 SUCCESS! MySQL running (5094)

設置密碼,遠程授權

設置密碼
  1. mysql安裝好之後進入mysql
mysql -uroot
  1. 查詢數據庫
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.01 sec)
  1. 切換mysql數據庫
mysql> use mysql;
Database changed
  1. 查看user, host, passWord信息
mysql> select user,host,password from user;
+------+-----------+----------+
| user | host      | password |
+------+-----------+----------+
| root | localhost |          |
| root | hadoop    |          |
| root | 127.0.0.1 |          |
| root | ::1       |          |
|      | localhost |          |
|      | hadoop    |          |
+------+-----------+----------+
6 rows in set (0.00 sec)
  1. 設置mysql密碼
mysql> update user set password=PASSWORD('root') where user='root';
Query OK, 4 rows affected (0.00 sec)
Rows matched: 4  Changed: 4  Warnings: 0
  1. 修改密碼之後, 查詢user表內容如下,說明在本地已經成功設置好了密碼
mysql> select user,host,password from user;
+------+-----------+-------------------------------------------+
| user | host      | password                                  |
+------+-----------+-------------------------------------------+
| root | localhost | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| root | hadoop    | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| root | 127.0.0.1 | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
| root | ::1       | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B |
|      | localhost |                                           |
|      | hadoop    |                                           |
+------+-----------+-------------------------------------------+
6 rows in set (0.00 sec)
設置遠程授權
  1. 通過新設置的密碼登錄mysql, 發現遇到如下問題, 說明用戶名或密碼不正確
[root@hadoop mysql]# mysql -uroot -proot
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

​ 在user表中存在字段host , 該字段表示可以訪問mysql的路徑地址, 從哪個節點可以訪問, 有這個字段來決定

  1. 所以要授權遠程登錄, 則需要修改host字段, 增加一條信息, 表示任意節點都可以訪問mysql, 用%來表示任意
mysql> update user set host='%' where user='root' and host='127.0.0.1';
  1. 完成以上語句後, 需要對修改的user進行刷新來生效語句操作
mysql> flush privileges;

  1. 完成以上操作之後驗證mysql用戶登錄,可以登錄成功
[root@hadoop mysql]# mysql -uroot -proot
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.5.47 MySQL Community Server (GPL)

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

配置hive元數據保存在mysql

需要在hive-site.xml配置文件總進行配置

  1. 設置hive鏈接mysql
  <property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://192.168.91.100:3306/metastore?createDatabaseIfNotExist=true</value>
    <description>JDBC connect string for a JDBC metastore</description>
  </property>

​ metastore: 默認保存hive中的元數據, 是一個數據庫的名字

  1. 設置jdbc的驅動類
  <property>
    <name>javax.jdo.option.ConnectionDriverName</name>
    <value>com.mysql.jdbc.Driver</value>
    <description>Driver class name for a JDBC metastore</description>
  </property>
  1. 設置mysql的用戶名
  <property>
    <name>javax.jdo.option.ConnectionUserName</name>
    <value>root</value>
    <description>Username to use against metastore database</description>
  </property>
  1. 設置mysql的密碼
  <property>
    <name>javax.jdo.option.ConnectionPassword</name>
    <value>root</value>
    <description>password to use against metastore database</description>
  </property>
  1. 完成以上的配置之後, 需要在hive/lib下邊存放jdbc的驅動包, 上傳好驅動包之後最好修改權限
 sudo chown -R hadoop:hadoop mysql-connector-java-5.1.31.jar 
  1. 將驅動包拷貝到hive目錄下的lib文件夾
cp mysql-connector-java-5.1.31.jar /opt/app/apache-hive-1.2.1-bin/lib/
  1. 到hive的lib下檢查是否拷貝成功

  2. 配置完成, 退出hive重新進入, 檢查mysql中是否創建了metastore數據庫, 如果創建成功, 則說明配置成功

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| metastore          |
| mysql              |
| performance_schema |
| test               |
+--------------------+

hiveserver2

1. beeline方式的連接

相當於在hive中啓動一個服務器端, 客戶端可以遠程連接該hive, hiveserver2不用安裝, 直接在hive/bin目錄下啓動

bin/hiveserver2

hiveserver2的服務啓動之後, 可以通過bin/beeline客戶端進行連接

官方實例:

!connect jdbc:hive2://localhost:10000 scott tiger

按照官方提供實例, 連接hiveserver2 測試能否連接成功

!connect jdbc:hive2://hadoop:10000 hadoop 123456

2. jdbc的方式連接

package org.hive.server;

import java.sql.SQLException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.DriverManager;

public class HiveJdbcClient {

	 private static String driverName = ""org.apache.hive.jdbc.HiveDriver"";
	 
	  /**
	   * @param args
	   * @throws SQLException
	   */
	  public static void main(String[] args) throws SQLException {
	      try {
	      Class.forName(driverName);
	    } catch (ClassNotFoundException e) {
	      // TODO Auto-generated catch block
	      e.printStackTrace();
	      System.exit(1);
	    }
	    //replace ""hive"" here with the name of the user the queries should run as
	    Connection con = DriverManager.getConnection(""jdbc:hive2://10.0.152.235:10000/default"", ""hive"", """");
	    Statement stmt = con.createStatement();
	    
	    String sql = ""show tables"";
	    System.out.println(""Running: "" + sql);
	    ResultSet res = stmt.executeQuery(sql);
	    if (res.next()) {
	      System.out.println(res.getString(1));
	    }
	 }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章