首页 > 其他分享 >新能源趋势下一个简单的数仓项目,助力理解数仓模型

新能源趋势下一个简单的数仓项目,助力理解数仓模型

时间:2024-01-08 15:37:55浏览次数:34  
标签:数仓 助力 dwd 模型 meter solar sql date spark


1.立项背景

目前国家政策的主导之下,新能源相关项目和公司的竞争愈演愈烈,很多新能源公司开始大规模的布局数仓,来从自己的产生的大量的数据中提取价值,进而在新能源市场有自己的一席之地。那么本项目就是以此为背景,结合spark sql,为大家从0到1构建一个“麻雀虽小五脏俱全”的项目

这里假设我们的数据源是一个新能源公司的数据库,包含以下几张表:electricity_meter, solar_panel, weather_data。这些表包含了电表读数、太阳能板数据和天气数据等信息。其中相关的表结构如下:

1.electricity_meter表结构

id:电表ID
date:日期
energy_consumption:能量消耗量
location:地点

2.solar_panel表结构

id:太阳能板ID
date:日期
solar_power:太阳能发电量
location:地点

3.weather_data表结构

id:天气数据ID
date:日期
temperature:温度
humidity:湿度
location:地点

示例数据

electricity_meter表示例数据

| id | date       | energy_consumption | location |
|----|------------|--------------------|----------|
| 1  | 2023-07-01 | 100                | New York |
| 2  | 2023-07-01 | 80                 | London   |
| 3  | 2023-07-02 | 120                | New York |
| 4  | 2023-07-02 | 90                 | London   |

solar_panel表示例数据

| id | date       | solar_power | location |
|----|------------|-------------|----------|
| 1  | 2023-07-01 | 50          | New York |
| 2  | 2023-07-01 | 40          | London   |
| 3  | 2023-07-02 | 60          | New York |
| 4  | 2023-07-02 | 45          | London   |

weather_data表示例数据

| id | date       | temperature | humidity | location |
|----|------------|-------------|----------|----------|
| 1  | 2023-07-01 | 30          | 70       | New York |
| 2  | 2023-07-01 | 25          | 65       | London   |
| 3  | 2023-07-02 | 32          | 75       | New York |
| 4  | 2023-07-02 | 28          | 68       | London   |

2.需求分析

我们的目标是将新能源公司的数据整合到数仓中,以支持分析和报表需求。我们关注的指标可能包括每日电量消耗、太阳能发电量、天气对发电量的影响等。

新能源趋势下一个简单的数仓项目,助力理解数仓模型_大数据

3.需求拆解

1.ODS层(操作数据存储)

创建ODS数据库,并在该数据库中创建以下表:

electricity_meter_ods
solar_panel_ods
weather_data_ods

2.DWD层(明细数据存储)

创建DWD数据库,并在该数据库中创建以下表:

electricity_meter_dwd
solar_panel_dwd
weather_data_dwd

3.DWS层(宽表数据存储) 

创建DWS数据库,并在该数据库中创建以下表:

daily_energy_usage_dws
solar_power_generation_dws

4.DIM层(维度数据存储)

创建DIM数据库,并在该数据库中创建以下表:

date_dim
location_dim

5.ADS层(分析数据存储)

创建ADS数据库,并在该数据库中创建以下表:

daily_energy_report_ads
solar_power_report_ads

接下来,我们以Scala为开发语言,Spark为计算引擎,演示一个完整的项目代码,非常容易理解一个业务的数仓开发建设。

object NewEnergy {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder
      .appName("New Energy Data Warehouse Project")
      .master("local")
      
      .config("hive.exec.dynamic.partition", "true")
      
      .config("hive.exec.dynamic.partition.mode", "nonstrict")
      .enableHiveSupport()
      .getOrCreate()

    val url = "jdbc:mysql://hadoop001:3306/test?useSSL=false"
    val properties: Properties = new Properties()
    properties.put("driver", "com.mysql.jdbc.Driver")
    properties.put("user", "root")
    properties.put("password", "root")

     
    val electricity_meter_df = spark.read.jdbc(url, "electricity_meter", properties)
    val solar_panel_df = spark.read.jdbc(url, "solar_panel", properties)
    val weather_data_df = spark.read.jdbc(url, "weather_data", properties)

    
    spark.sql("CREATE DATABASE IF NOT EXISTS ods")
    spark.sql("USE ods")
    electricity_meter_df.write.saveAsTable("electricity_meter_ods")
    solar_panel_df.write.saveAsTable("solar_panel_ods")
    weather_data_df.write.saveAsTable("weather_data_ods")

    
    
    spark.sql("CREATE DATABASE IF NOT EXISTS dwd")
    spark.sql("USE dwd")

    spark.sql("SELECT * FROM ods.electricity_meter_ods")
      .write
      .saveAsTable("electricity_meter_dwd")

    spark.sql("SELECT * FROM ods.solar_panel_ods")
      .write
      .saveAsTable("solar_panel_dwd")

    spark.sql("SELECT * FROM ods.weather_data_ods")
      .write
      .saveAsTable("weather_data_dwd")

    
    
    spark.sql("CREATE DATABASE IF NOT EXISTS dws")
    spark.sql("USE dws")
    spark.sql("""
             |SELECT
             |  date, SUM(energy_consumption) AS energy_usage
             |FROM
             |  dwd.electricity_meter_dwd
             |GROUP BY
             |  date
             |""".stripMargin)
      .write
      .saveAsTable("daily_energy_usage_dws")

    spark.sql("""
             |SELECT
             |  date, SUM(solar_power) AS solar_power_generation
             |FROM
             |  dwd.solar_panel_dwd
             |GROUP BY
             |  date
             |""".stripMargin)
      .write
      .saveAsTable("solar_power_generation_dws")

    
    
    spark.sql("CREATE DATABASE IF NOT EXISTS dim")
    spark.sql("USE dim")
    spark.sql("""
             |SELECT
             |  DISTINCT date
             |FROM
             |  dwd.electricity_meter_dwd
             |""".stripMargin)
      .write
      .saveAsTable("date_dim")

    spark.sql("""
             |SELECT
             |  DISTINCT location
             |FROM
             |  dwd.solar_panel_dwd
             |""".stripMargin)
      .write
      .saveAsTable("location_dim")

    
    
    spark.sql("CREATE DATABASE IF NOT EXISTS ads")
    spark.sql("USE ads")
    spark.sql("""
             |SELECT
             |  d.date, u.energy_usage
             |FROM
             |  dim.date_dim d
             |JOIN
             |  dws.daily_energy_usage_dws u
             |ON
             |  d.date = u.date
             |""".stripMargin)
      .write
      .saveAsTable("daily_energy_report_ads")

    spark.sql("""
             |SELECT
             |  d.date, s.solar_power_generation
             |FROM
             |  dim.date_dim d
             |JOIN
             |  dws.solar_power_generation_dws s
             |ON
             |  d.date = s.date
             |""".stripMargin)
      .write
      .saveAsTable("solar_power_report_ads")
  }
}

4.附录:数据生成工具

public class DataGenerator {
    
    private static final String DB_URL = "jdbc:mysql://hadoop001:3306/test";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "root";

    
    private static final int NUM_RECORDS = 1000000; 

    public static void main(String[] args) {
        try {
            
            Class.forName("com.mysql.jdbc.Driver");

            
            Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);

            
            generateElectricityMeterData(conn);

            
            generateSolarPanelData(conn);

            
            generateWeatherData(conn);

            
            conn.close();
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
    }

    private static void generateElectricityMeterData(Connection conn) throws SQLException {
        String sql = "INSERT INTO electricity_meter (id, date, energy_consumption, location) VALUES (?, ?, ?, ?)";

        Random random = new Random();

        PreparedStatement stmt = conn.prepareStatement(sql);
        for (int i = 1; i <= NUM_RECORDS; i++) {
            stmt.setInt(1, i);
            stmt.setString(2, generateRandomDate());
            stmt.setInt(3, random.nextInt(200) + 1); 
            stmt.setString(4, generateRandomLocation());
            stmt.executeUpdate();
        }
        stmt.close();
    }

    private static void generateSolarPanelData(Connection conn) throws SQLException {
        String sql = "INSERT INTO solar_panel (id, date, solar_power, location) VALUES (?, ?, ?, ?)";

        Random random = new Random();

        PreparedStatement stmt = conn.prepareStatement(sql);
        for (int i = 1; i <= NUM_RECORDS; i++) {
            stmt.setInt(1, i);
            stmt.setString(2, generateRandomDate());
            stmt.setInt(3, random.nextInt(100) + 1); 
            stmt.setString(4, generateRandomLocation());
            stmt.executeUpdate();
        }
        stmt.close();
    }

    private static void generateWeatherData(Connection conn) throws SQLException {
        String sql = "INSERT INTO weather_data (id, date, temperature, humidity, location) VALUES (?, ?, ?, ?, ?)";

        Random random = new Random();

        PreparedStatement stmt = conn.prepareStatement(sql);
        for (int i = 1; i <= NUM_RECORDS; i++) {
            stmt.setInt(1, i);
            stmt.setString(2, generateRandomDate());
            stmt.setInt(3, random.nextInt(40) + 20); 
            stmt.setInt(4, random.nextInt(70) + 30); 
            stmt.setString(5, generateRandomLocation());
            stmt.executeUpdate();
        }
        stmt.close();
    }

    private static String generateRandomDate() {
        String baseDateStr = "2023-07-01";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate baseDate = LocalDate.parse(baseDateStr, formatter);
        List<String> dates = new ArrayList<>();

        
        for (int i = -10; i <= 0; i++) {
            LocalDate currentDate = baseDate.plusDays(i);
            String formattedDate = currentDate.format(formatter);
            dates.add(formattedDate);
        }

        
        for (int i = 1; i <= 10; i++) {
            LocalDate currentDate = baseDate.plusDays(i);
            String formattedDate = currentDate.format(formatter);
            dates.add(formattedDate);
        }
        int i = new Random().nextInt(21);
        return dates.get(i);
    }

    private static String generateRandomLocation() {
        
        
        
        String[] locations = {"New York", "London", "Tokyo", "Sydney", "Beijing", "Shanghai", "Tianjin"};
        int randomIndex = new Random().nextInt(locations.length);
        return locations[randomIndex];
    }
}

新能源趋势下一个简单的数仓项目,助力理解数仓模型

标签:数仓,助力,dwd,模型,meter,solar,sql,date,spark
From: https://blog.51cto.com/u_15346267/9145398

相关文章

  • 走进CSIG|文档图像大模型在智能文档处理领域中的应用
    ⭐️前言2023年12月28-31日,第十九届中国图象图形学学会青年科学家会议在中国广州召开。本次会议由中国图象图形学学会主办,琶洲实验室、华南理工大学、中山大学、中国图象图形学学会青年工作委员会承办。王耀南院士、谭铁牛院士、中山大学赖剑煌教授、华南理工大学徐向民副校长、许勇......
  • 雅意2.0:打造专为中文优化的300亿参数多语言模型
    前言雅意2.0,作为一款专注于中文语境的开源大型语言模型,其在多语言处理方面的能力尤为突出。该模型不仅具有300亿参数规模的庞大体量,还在多个关键领域取得了显著的技术突破。Huggingface模型下载:https://huggingface.co/wenge-research/AI快站模型免费加速下载:https://aifasthub.com......
  • 科技云报道:“存算一体”是大模型AI芯片的破局关键?
    科技云报道原创。在AI发展历史上,曾有两次“圣杯时刻”。第一次发生在2012年10月,卷积神经网络(CNN)算法凭借比人眼识别更低的错误率,打开了计算机视觉的应用盛世。第二次是2016年3月,DeepMind研发的AI程序AlphaGo,战胜世界围棋冠军李世石,让全世界惊叹于“人工智能”的实力。这两次“圣杯......
  • 文本挖掘的文本聚类与主题模型:实现信息挖掘的关键
    1.背景介绍文本挖掘是一种通过对文本数据进行挖掘和分析来发现隐藏知识和模式的方法。它广泛应用于各个领域,如自然语言处理、数据挖掘、信息检索等。文本聚类和主题模型是文本挖掘中两个核心技术,它们可以帮助我们对文本数据进行有效的分类和主题分析。文本聚类是指将文本数据分为多......
  • Ngram模型在机器翻译中的应用与挑战
    1.背景介绍机器翻译是自然语言处理领域的一个重要研究方向,其目标是将一种自然语言文本自动翻译成另一种自然语言文本。在过去的几十年里,机器翻译技术发展了很长一段时间,从基于规则的方法(如规则引擎和统计规则)开始,到基于模型的方法(如统计模型、深度学习模型等)发展。在这些方法中,N-gr......
  • 大模型中,温度系数(temperature)的PyTorch和TensorFlow框架
    在大模型中,温度系数(temperature)通常用于调整模型的输出概率分布。温度系数的概念来源于物理学的热力学,它可以理解为一个“热度”值,用于控制模型的输出稀疏程度。温度系数越大,模型输出越倾向于给出较高的概率值,表现为“热情”;温度系数越小,模型输出越倾向于给出较低的概率值,表现为“......
  • AI大模型引领数智未来
    AI大模型引领数智未来作者:坚果华为HDE,润开鸿生态技术专家,坚果派创始人,OpenHarmony布道师,开发者联盟优秀讲师,2023年开源之夏导师,2023年OpenHarmony应用创新赛导师,OpenHarmony金融应用创新赛导师,RISC-V+OpenHarmony应用创意赛导师,OpenHarmony三方库贡献者,开放原子开源基金会技术+生......
  • 【领先实践之离散制造行业】MOM全场景,助力光伏单晶行业降本增效
    在光伏单晶行业中,企业面临着提高效率、降低成本和增强市场竞争力的挑战,为了应对这些挑战,用友MOM(制造运营管理)全场景领先实践,基于在光伏单晶行业的成功应用,为光伏单晶行业提供了全方位的生产管理支持。该方案具有以下5大优势:优化供应链通过数据共享和分析,提供实时可视化的供应链信息......
  • 对话式搜索:基于OpenSearch向量检索版+大模型的实践
    随着人工智能技术的不断发展,对话式搜索已成为一种便捷、高效的信息获取方式。基于OpenSearch向量检索版和大模型的对话式搜索,更是将这一技术推向了新的高度。本文将为你揭示这一技术的奥秘,并指导你如何搭建自己的对话式搜索系统。一、技术原理OpenSearch向量检索版:OpenSearch是一种......
  • 人工智能时代的大模型算法
    文心大模型4.0是百度最新推出的一代知识增强大语言模型,它是基于深度学习技术构建的,通过与海量数据结合,能够为人工智能应用提供强大的算法支持。本文将详细介绍文心大模型4.0的核心技术、应用场景和优势,以及如何使用它来提高人工智能应用的性能。一、文心大模型4.0的核心技术文心大......