Gradle实战:执行sql操作hive数据库

查看原文:http://blog.csdn.net/u010818425/article/details/52490628

Gradle实战系列文章: 
《Gradle基本知识点与常用配置》 
《Gradle实战:Android多渠道打包方案汇总》 
《Gradle实战:不同编译类型的包同设备共存》 
《Gradle实战:发布aar包到maven仓库》


本文将介绍使用groovy+sql的脚本,实现从hive抓取数据,为方便理解,重要语句有详细注释,关键处已标明“关键点”;在阅读本文过程中,如对groovy还不是很熟悉的读者可以查看《 Gradle基本知识点与常用配置》这篇文章

入门例子

Gradle简单操作mysql数据库

import groovy.sql.Sql 

class GroovySqlExample1{
    static void main(args) {
        sql = Sql.newInstance("jdbc:mysql://localhost:3306/tablename", "account", "password", "org.gjt.mm.mysql.Driver")
        sql.eachRow("select * from tablename"){
            row | println row.word_id + " " + row.spelling + " " + row.part_of_speech
            //“row”表示查询到的每一行数据,“row.word_id”表示“word_id”这个字段的值
        }
    }
}

这是一个使用Gradle操作mysql数据库的入门例子,配置好数据库地址、驱动、账号、密码就可以执行sql语句操作数据库了,但是现在越来越多的公司都转向使用分布式存储,以下我们来详细介绍一下Gradle操作hive数据库的实例(当然,你需要有这样一个数据库环境)。


实战例子

以获取udid(设备唯一识别码)为例,条件是:1、近两周内打开过我们app(即我们后台系统有其访问记录),我们认为这些是活跃用户;2、满足条件1的各城市用户中,各取20%的用户。以下分为5各部分来讲述我们的实现方案:sql脚本、配置文件、groovy代码、使用方法、数据产出。

1. getUdid.sql中的sql脚本:

首先,新建一个android工程,无需任何java代码;然后在module中新建一个名为“getUdid.sql“的文件,里面存放的就是我们用于查询数据库的sql脚本;但这个脚本还可以通过gradle运行过程中动态拼接一些参数,下文会有介绍。

SELECT count(DISTINCT udid) AS allCount FROM tablename WHERE dt>=date_sub(current_date,14);
SELECT DISTINCT udid FROM tablename WHERE dt>=date_sub(current_date,14)

2. hive.properties中的配置数据

再在module中新建一个名为“hive.properties“的配置文件,用于存放连接数据库所需的相关参数。

HiveUrl=jdbc:hive2://host:port/basename?useUnicode=true&characterEncoding=utf8
Account=xxx
Password=xxx
Driver=org.apache.hive.jdbc.HiveDriver //连接hive所用的驱动

注:上述的HiveUrl中,scheme使用的是hive2,因此与其配套的驱动是org.apache.hive.jdbc.HiveDriver,如果使用的是早期的hive,则scheme是hive,其配套的驱动是org.apache.hadoop.hive.jdbc.HiveDriver

3. groovy代码:

import groovy.sql.Sql  //关键点1

apply plugin: ‘java‘
apply plugin: ‘groovy‘
apply plugin: ‘maven‘

repositories {
    mavenCentral()
}

configurations {
    driver  //关键点2
}

dependencies {
    driver ‘org.apache.hive:hive-jdbc:2.1.0‘ //数据库连接驱动依赖,关键点3
}

//数据库连接驱动下载,关键点4
URLClassLoader loader = GroovyObject.class.classLoader
configurations.driver.each { File file ->
    loader.addURL(file.toURL())
}

task run << {
    def File propFile = new File(‘hive.properties‘) //“hive.properties”为自定义的配置文件,上文有介绍
    if (propFile.canRead()) {
        def Properties props = new Properties()
        props.load(new FileInputStream(propFile))

        if (props != null && props.containsKey(‘HiveUrl‘) && props.containsKey(‘Account‘)
                && props.containsKey(‘Password‘) && props.containsKey(‘Driver‘)) {
            //从配置文件中读取各参数
            String hiveUrl = props[‘HiveUrl‘]//数据库地址
            String account = props[‘Account‘]//访问数据库的账号
            String password = props[‘Password‘]//密码
            String driver = props[‘Driver‘] //连接数据库的驱动类名
            String os = System.properties[‘os‘] //读取命令行设置的手机系统类型(设置见下文“使用方法”中的命令行)
            String ver = System.properties[‘ver‘]//读取命令行设置的app版本号(设置见下文“使用方法”中的命令行)

            def sql = Sql.newInstance(hiveUrl, account, password, driver)//建立数据库连接,关键点5

            String udidName = "udid_" //存放udid的文件名
            String summaryName = "summary_" //存放各城市概况的文件名
            if (os.equals("Android")) {
                udidName += "android.txt"
                summaryName += "android.txt"
            } else {
                udidName += "ios.txt"
                summaryName += "ios.txt"
            }

            String dirPath = getRootDir().toString() + ‘/result/‘ //结果存放路径
            def dir = new File(dirPath)
            if (!dir.exists()) {
                dir.mkdirs()
            }

            String udidPath = dirPath + ‘/‘ + udidName //udid文件路径
            String summaryPath = dirPath + ‘/‘ + summaryName //各城市概况文件路径
            def udidFile = new File(udidPath)
            def summaryFile = new File(summaryPath)
            if (udidFile.exists()) {
                udidFile.delete()
            }
            udidFile.createNewFile()
            if (summaryFile.exists()) {
                summaryFile.delete()
            }
            summaryFile.createNewFile()

            def resultPrintWriter = udidFile.newPrintWriter()
            def summaryPrintWriter = summaryFile.newPrintWriter()

            //制表
            summaryPrintWriter.write(‘\n‘)
            summaryPrintWriter.write(os + "用户情况")
            summaryPrintWriter.write(‘\n‘)
            summaryPrintWriter.write(‘-------------------‘)
            summaryPrintWriter.write(‘\n‘)
            summaryPrintWriter.write(" 城市" + "   总数" + "  抽取")
            summaryPrintWriter.write(‘\n‘)
            summaryPrintWriter.write(‘-------------------‘)
            summaryPrintWriter.write(‘\n‘)

            def citys = [‘北京市‘, ‘上海市‘, ‘广州市‘, ‘深圳市‘]
            int allcount = 0 // 活跃用户总数
            int allExtracted = 0 // 抽取20%的用户数
            try {
                //各个城市遍历
                citys.each {
                    city ->
                        resultPrintWriter.write(city + ‘:‘)
                        resultPrintWriter.write(‘\n‘)
                        resultPrintWriter.write(‘--------------------------------------‘)
                        resultPrintWriter.write(‘\n‘)
                        boolean isGetCount = true
                        int num = 0
                        // 读取sql脚本,每句以分号分隔,下方还需动态拼接参数
                        new File(‘getUdid.sql‘).text.split(";").each { //“getUdid.sql”里面为查询udid的sql语句,下文有介绍
                            sqlTemp ->
                                //动态拼接参数
                                String sqlString = sqlTemp +
                                        ‘ AND city=‘ + "‘" + city + "‘" +
                                        ‘ AND os=‘ + "‘" + os + "‘" +
                                        ‘ AND ver=‘ + "‘" + ver + "‘"
                                if (isGetCount) { // 执行第一句sql,获取该城市总活跃用户中的20%
                                    println sqlString
                                    sql.eachRow(sqlString) { // 执行sql,关键点6
                                        num = it.allcount * 0.2 // 总数的20%
                                        allcount += it.allcount
                                        allExtracted += num

                                        //制表
                                        summaryPrintWriter.write(city + "  " + it.allcount + getCount(it.allcount) + num)
                                        summaryPrintWriter.write(‘\n‘)
                                        summaryPrintWriter.write(‘-------------------‘)
                                        summaryPrintWriter.write(‘\n‘)
                                    }
                                    isGetCount = false
                                } else { // 执行第二句sql,获取该城市总活跃用户数前20%的udid
                                    sqlString = sqlString + " LIMIT " + num // 取前num个数据,动态拼接条件
                                    println sqlString
                                    sql.eachRow(sqlString) { // 执行sql
                                        if (it.udid != null && it.udid != ‘‘) {
                                            resultPrintWriter.write(it.udid + ",")
                                            resultPrintWriter.write(‘\n‘)
                                        }
                                    }
                                }
                        }
                        resultPrintWriter.write(‘--------------------------------------‘)
                        resultPrintWriter.write(‘\n‘)
                }

                //制表
                summaryPrintWriter.write("  累计 " + " " + allcount + getCount(allcount) + " " + allExtracted)
                summaryPrintWriter.write(‘\n‘)
                summaryPrintWriter.write(‘-------------------‘)
                summaryPrintWriter.write(‘\n‘)
                summaryPrintWriter.write("统计日期:" + releaseTime())
                summaryPrintWriter.write(‘\n‘)
            } catch (Exception e) {
                println e.message
            }

            //关闭打印
            resultPrintWriter.flush()
            summaryPrintWriter.flush()
            resultPrintWriter.close()
            summaryPrintWriter.close()
        }
    }
}

//获取系统时间
def releaseTime() {
    return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}

//模拟制表符,用于summary文件里面制作表格
String getCount(i) {
    int temp = i
    int count = 0
    while (temp > 0) {
        temp = temp / 10
        count++
    }

    String space = ‘‘
    if (count == 1) {
        space = "     "
    } else if (count == 2) {
        space = "    "
    } else if (count == 3) {
        space = "   "
    } else if (count == 4) {
        space = "  "
    }
    return space
}

4. 使用方法

本地需安装Gradle且配置环境变量;然后打开终端,按以下步骤输入命令(第一次执行会下载hive数据库驱动,耗时较长):

  • 进入到工程目录下(假设module名为executeSql):

    cd executeSql
  • 抓取android数据:
    gradle run -Dos=‘Android‘ -Dver=‘1.0.0‘
  • 抓取iOS数据:
    gradle run -Dos=‘iPhone OS‘ -Dver=‘2.0.0‘

    注:上述命令中,“-D”表示设置参数,在groovy代码中有接收参数的语句String os = System.properties[‘os‘]

以android为例,开始执行后,每个城市都会执行以下两句sql,即上述gradle脚本动态拼接成的sql:

SELECT count(DISTINCT udid) AS allCount FROM tablename WHERE dt>=date_sub(current_date,14) AND city=‘北京市‘ AND os=‘Android‘ AND ver=‘1.0.0‘;
SELECT DISTINCT udid FROM tablename WHERE dt>=date_sub(current_date,14) AND city=‘北京市‘ AND os=‘Android‘ AND ver=‘1.1.0‘ LIMIT 2000

5. 数据产出

数据产出为两个文件,一个是各城市用户的总体情况,另一个是各城市用户z红20%的udid数据列表;

  • 各城市用户情况,summary_android.txt

    
    Android用户情况
    -------------------
    
     城市   总数  抽取
    -------------------
    
    北京市  10000 2000
    -------------------
    
    上海市  20000 4000
    -------------------
    
    广州市  30000 6000
    -------------------
    
    深圳市  40000 8000
    -------------------
    
      累计 100000 20000
    -------------------
    
    统计日期:2016-09-09
    
  • 各城市udid,udid_summary.txt(仅作示意)
    
    北京市:
    --------------------------------------
    
    00123456-2c9c-4ab7-a256-4b86a2490318,
    00234567-f9fb-4059-a1b8-49514fb17ac0,
    
    ...
    --------------------------------------
    
    上海市:
    --------------------------------------
    
    00345678-4910-4db5-b82c-42f85450c85c,
    00456789-1047-470c-9bf2-af326fdac7f1,
    
    ...
    --------------------------------------
    
    广州市:
    --------------------------------------
    
    01234567-d69f-40fa-aabd-88ac19f542cf,
    02345678-b1c2-4005-a418-f6d1704b7f81,
    
    ...
    --------------------------------------
    
    深圳市:
    --------------------------------------
    
    03456789-0413-4cd1-9214-8544a07eecec,
    04567891-4ac2-49cd-a1c8-f49c5edd9d9b,
    
    ...
    --------------------------------------
    

深入学习

查看原文:http://blog.csdn.net/u010818425/article/details/52490628

时间: 2024-10-03 07:38:20

Gradle实战:执行sql操作hive数据库的相关文章

批处理--执行sql(mysql数据库)

@echo off rem test.sql文件 for %%i in (test.sql) do ( echo excute %%i mysql -u用户名 -p密码 -D数据库名 < %%i ) echo success pause 批处理--执行sql(mysql数据库),布布扣,bubuko.com

mysql数据库批量执行sql文件对数据库进行操作【windows版本】

起因: 因工作需要,在本机测试环境升级mysql数据库,需逐条执行mysql数据库的sql文件对数据库进行升级,因此找了些关于mysql的文章,对批量升级数据库所需的sql文件进行升级. 整理思路: 首先,需要对所需升级的sql所在目录的sql文件进行遍历.生成新的批量执行sql文件.想到是windows系统安装的mysql,首先想到使用bat进行sql文件的生成: 生成sql文件后,还需要使用bat文件连接到数据库,并使用新生成的sql文件进行升级. 想到升级的过程中还有可能字符集出现问题,因

微信PK10平台开发Go实战--go语言操作sqlite数据库

生命不止,继续 go go go !!!微信PK10平台开发 继续与大家分享,go语言的实战,今天介绍的是如何操作sqlite数据库. 何为sqlite3? SQLite is a self-contained, high-reliability, embedded, full-featured, public-domain, SQL database engine. 最主要的是,sqlite是一款轻型的数据库 database/sql包 go中有一个database/sql package,我

ADO.NET——Command(执行SQL) &amp; DataReader(读取数据库)

一,关于两个对象的基础知识 1,Command Command对象主要用于对数据源执行SQL命令并返回结果. ADO.NET提供了Connection来连接数据库,同时也提供了Command对象来查询数据库.同Connection对象一样,Command也有两种:OleDbCommand和SqlCommand.其区别同Connection对象. Command对象有一个属性:CommandType(sql语句或者存储过程):三个重要方法:ExecuteNonQuery(增.删.改影响的行数).E

Sql操作 - 删除数据库重复项

TableName : yourtablename Existed Fields: yourfield1,yourfield2, handle....... 删除指定字段yourfield1为MatchedString所所有重复项 delete * from yourtablename where yourfield1='MatchedString' and handle not in (select distinct min(Handle) from chnl where yourfield1

Gradle实战:Android多渠道打包方案汇总

查看原文:http://blog.csdn.net/u010818425/article/details/52319382 Gradle实战系列文章: <Gradle基本知识点与常用配置> <Gradle实战:不同编译类型的包同设备共存> <Gradle实战:发布aar包到maven仓库> <Gradle实战:执行sql操作hive数据库> 本文将延续之前几篇博客的风格,先从基本概念入手,这有助于我们对后文的理解: 在后续的代码中如果忘了某个概念的具体意义,

Gradle实战:发布aar包到maven仓库

查看原文:http://blog.csdn.net/u010818425/article/details/52441711 Gradle实战系列文章: <Gradle基本知识点与常用配置> <Gradle实战:Android多渠道打包方案汇总> <Gradle实战:不同编译类型的包同设备共存> <Gradle实战:执行sql操作hive数据库> aar简介 aar文件是Google为Android开发所设计的一种library格式,全名为Android Ar

EF Core中执行Sql语句查询操作之FromSql,ExecuteSqlCommand,SqlQuery

一.目前EF Core的版本为V2.1 相比较EF Core v1.0 目前已经增加了不少功能. EF Core除了常用的增删改模型操作,Sql语句在不少项目中是不能避免的. 在EF Core中上下文,可以返货DbConnection ,执行sql语句.这是最底层的操作方式,代码写起来还是挺多的. 初次之外 EF Core中还支持 FromSql,ExecuteSqlCommand 连个方法,用于更方便的执行Sql语句. 另外,目前版本的EF Core 不支持SqlQuery,但是我们可以自己扩

Spark SQL with Hive

前一篇文章是Spark SQL的入门篇Spark SQL初探,介绍了一些基础知识和API,但是离我们的日常使用还似乎差了一步之遥. 终结Shark的利用有2个: 1.和Spark程序的集成有诸多限制 2.Hive的优化器不是为Spark而设计的,计算模型的不同,使得Hive的优化器来优化Spark程序遇到了瓶颈. 这里看一下Spark SQL 的基础架构: Spark1.1发布后会支持Spark SQL CLI , Spark SQL的CLI会要求被连接到一个Hive Thrift Server