【postgresql初级使用】可以存储数据的视图-物化视图,加速大数据下的查询分析

物化视图

专栏内容

  • postgresql使用入门基础
  • 手写数据库toadb
  • 并发编程

个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

文章目录

  • 物化视图
  • 概述
  • 原理机制
  • materialize view 创建
    • 语法说明
    • 使用案例
      • 初始化数据
      • 物化视图使用
  • materialize view 刷新数据
  • materialize view 删除
  • 总结
  • 结尾

概述


本节主要分享物化视图(materialize view)的基础知识,分为原理机制,创建,数据刷新,以及删除等小节。

在原理机制一节,会与普通view对比不同点,它们执行机制的差异;之后的各小节结合案例分享语法与使用场景。

原理机制


先来看看普通的view ,它只是记录一条view定义时的查询语句,从view查询的SQL,会被重写,用view定义的语句进行替换,然后执行查询,实际是从数据表中查询。

执行流程 如下:

select * from vw_employee;->查询优化器->重写为 select * from (select * from employee) as vw_employee; -> 执行器 -> 返回结果

每次从view 查询时,都会执行一次view定义的查询语句,view 本身不会存储数据。

下面来看看materialize view, 它在定义时会将数据保存一份,它有自己存储数据,但是它不会自动与主表进行数据同步,也就是主表的数据变化了,物化视图中的备份数据不会变化,需要手动进行同步。

执行流程如下:

select * from mvw_emplyee; -> 查询优化器 -> 执行器 -> 返回结果

如果对某相view访问很频繁时,结果集只生成一次,后面都是直接查结果集就可以,会大大节省时间,尤其对于大数据分析,每次结果集的生成都需要数秒,甚至数分钟,每次都进行结果生成,那是不可想象的一件事。

因为物化视图会保存源表的数据,所以它不能被修改,避免数据的分叉,这不像前一节介绍的updatable view。

下面我们来介绍一下物化视图的使用。

materialize view 创建


语法说明

物化视图的创建语法如下:

CREATE MATERIALIZED VIEW view_name
AS
query_sql
WITH [No] DATA;

物化视图与普通视图的创建语法类似,区别如下:

  • 这里使用关键字materialized来指示视图的类型为物化视图;
  • 定义的最后使用with datawith no data来指定创建后的物化视图,是否需要同步数据;
    如果不指定,默认为前者,在创建完后,会同步主表的数据;
    如果选择with no data,则创建完后没有数据,并且不能查询,必须先同步数据;

使用案例

下面我们分享一个案例,它是一个大数据分析平台,生产库每天会产生上千万条的订单数据,而分析库每天晚上定时生成分析报表,来指导第二天的库存备货以及调货运输。

初始化数据

  • 创建产品与订单表。
-- 创建产品表  
CREATE TABLE products (  product_id INT PRIMARY KEY,  product_name VARCHAR(255) NOT NULL,  price DECIMAL(10, 2) NOT NULL,  category VARCHAR(255)  
);  -- 创建订单表  
CREATE TABLE orders (  order_id INT PRIMARY KEY,  product_id INT,  quantity INT NOT NULL,  region VARCHAR(255) NOT NULL,  order_date DATE NOT NULL,  FOREIGN KEY (product_id) REFERENCES Products(product_id)  
);
  • 这里使用一个生成随机字符串的存储过程,来辅助我们生成模拟数据,它的定义如下:
CREATE OR REPLACE FUNCTION generate_random_string(length INTEGER)  
RETURNS VARCHAR 
LANGUAGE plpgsql
AS $$
DECLARE  result VARCHAR(255) := '';  chars TEXT[] := ARRAY['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']; BEGIN  FOR i IN 1..length LOOP  result := result || chars[1+(random() * (array_length(chars, 1)-2))::int];  END LOOP;  RETURN result;  
END $$;  
  • 生成10万条商品的数据,同时生成100万条的订单数据。

生成商品数据;

INSERT INTO products (product_id,product_name,price,category )
SELECTid, generate_random_string(10),  -- 假设商品名字长度为 10(random() * 1000)::numeric(10,2),  -- 随机价格在 0 到 1000 之间'Category' || (random() * 10)::int  -- 假设有 10 个不同的商品类别
FROM generate_series(1, 100000) as id;

生成订单数据,其中商品的ID在10万以内随机生成。

INSERT INTO orders (order_id,product_id,quantity,region,order_date)
SELECTid, 1+random()*99999,(random() * 10000)::int,'region' || (random() * 22)::int,current_date - floor((random() * 360))::int rand_date
FROM generate_series(1, 1000000) as id;

物化视图使用

报表中的一个指标项查询SQL如下:

-- 查询每个区域的销量
SELECT region, SUM(quantity) AS total_salesFROM ordersGROUP BY region;

我们开启psql中的时间统计,看看执行一次统计花费的时间。

postgres=# \timing on
Timing is on.
postgres=# SELECT region, SUM(quantity) AS total_sales
postgres-#     FROM orders
postgres-#     GROUP BY region;region  | total_sales
----------+-------------region0  |   114114062region1  |   226243565region10 |   227494628region11 |   227777263region12 |   228053045region13 |   228127572region14 |   227847192region15 |   226668865region16 |   227167622region17 |   226283956region18 |   227486573region19 |   226798204region2  |   227236551region20 |   229110138region21 |   228462753region22 |   112870077region3  |   225945462region4  |   230059348region5  |   226837565region6  |   228821897region7  |   226570562region8  |   227755978region9  |   225983661
(23 rows)Time: 50.188 ms

看到结果生成了23条记录,花费了50ms时间。

之前我们使用的是普通视图或者是CTE语句,报表的生成需要花费整整一个晚上,因为每次执行都需要重新进行结果的生成。

后来我们将这个指标项创建为物化视图的形式,只需要同步数据的时间就可以了,不仅节省了时间,而且不再长时间占用计算资源。

下面分享给大家这个方法,先来创建一个物化视图:

postgres=# create materialized view mvw_regiion_sales AS SELECT region, SUM(quantity) AS total_sales
postgres-#     FROM orders
postgres-#     GROUP BY region;
SELECT 23
Time: 52.976 ms

创建物化视图时,没有指定with no data时,默认会同步数据到物化视图中,可以看到花费了52ms,与上面查询的时间相当。

此时我们查看各区域的销量时,就可以从物化视图中来查看。

postgres=# select * from mvw_regiion_sales ;region  | total_sales
----------+-------------region0  |   114114062region1  |   226243565region10 |   227494628region11 |   227777263region12 |   228053045region13 |   228127572region14 |   227847192region15 |   226668865region16 |   227167622region17 |   226283956region18 |   227486573region19 |   226798204region2  |   227236551region20 |   229110138region21 |   228462753region22 |   112870077region3  |   225945462region4  |   230059348region5  |   226837565region6  |   228821897region7  |   226570562region8  |   227755978region9  |   225983661
(23 rows)Time: 0.260 ms

多次查看各区域的销量,花费时间都不到1ms,是原来的五十分之一,大大节省了时间和资源。

materialize view 刷新数据


当白天运营时,商品表和订单表都可能发生变化,而区域销量的物化视图中的数据如何更新呢?

在订单表中新增一条订单记录,新增区域region100,这是一个新区域产生了订单。

postgres=# insert into orders values(1000001, 1000,10000,'region100','2023-12-03');
INSERT 0 1
Time: 8.132 ms

查看物化视图,还是前一天的值,它不会自动更新数据。

postgres=# select * from mvw_regiion_sales where region='region100';region | total_sales
--------+-------------
(0 rows)Time: 0.259 ms

对物化视图中的数据进行刷新,就会同步源表中的数据。

postgres=# refresh materialized view mvw_regiion_sales ;
REFRESH MATERIALIZED VIEW
Time: 54.042 ms

可以看到执行时间大概为54ms。

postgres=# select * from mvw_regiion_sales where region='region100';region   | total_sales
-----------+-------------region100 |       10000
(1 row)Time: 0.265 ms

再次查询时,已经有了新数据。

在执行refresh materialize view命令时,会从源表中加载数据到物化视图中,此时会对源表进行加锁,使得源表不能进行操作。

如果要并发执行物化视图的刷新,可以增加关键字concurrently,执行命令 refresh materialize view concurrently。当前并发执行的前提是,当前物化视图必须有唯一性索引列。

materialize view 删除


删除物化视图的SQL语法,类似与普通view。

drop materialize view view_name;

如果有关联的视图,可以增加关键字cascade,进行级联删除。

总结


在大数据分析场景下,物化视图是一个非常高效的记录中间报表结果的方法,避免多次重复执行。

结尾


非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/7394.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HIVE统计WordCount

HIVE WORDCOUNT 目录 HIVE WORDCOUNT 一、WORDCOUNT 1.我们先创建一个新的数据库 2.创建表并插入数据 3.统计WORDCOUNT 4.UNION ALL 用法 5.WITH AS 用法 1.WORDCOUNT 1)我们先创建一个新的数据库 create database learn3;use learn3; 2)创建表…

知识图谱融入RAG模型:LinkedIn重塑智能客服新范式【附LeCun哈佛演讲PPT】

原文:Retrieval-Augmented Generation with Knowledge Graphs for Customer Service Question Answering 一、研究背景与问题 在客服领域,快速准确地匹配用户问题与历史工单,是提供优质回答的关键。传统的检索增强生成(Retrieval-Augmented Generation, RAG)方法虽…

分享5款PDF编辑软件

PDF编辑不易,有需要的朋友可以试试这5款专业软件,每一个都能直接在PDF文件上编辑,不同的软件对PDF可编辑的范围不同,大家可以按需求选用。 1.edge浏览器 Edge浏览器不仅是浏览网页的得力助手,还悄然成为了轻量级PDF管…

微信小程序开发秘籍:解锁音频录制与录音功能的奥秘

微信小程序开发秘籍:解锁音频录制与录音功能的奥秘 在微信小程序的开发旅程中,音频功能的集成可以极大地丰富用户体验,特别是在教育、娱乐、社交等领域。本文将引领你深入了解如何在微信小程序中实现音频录制和播放功能,从基本概…

2024蓝桥杯RSA-Theorem

方法1:直接使用工具yafu解题 yafu的使用方法 安装:解压后直接使用即可,在文件包内,执行命令终端,输入命令行 1、如果数比较小,进入该文件的目录后可以直接使用: yafu-x64 factor(n) 如果是powershell&…

Element-UI快速入门:构建优雅的Vue.js应用界面

Element-UI是一套基于Vue.js的组件库,提供了丰富的UI组件和交互效果,帮助开发者快速构建出美观、功能丰富的Web应用界面。本文将介绍如何快速入门Element-UI,并搭建一个简单的示例界面。 步骤一:安装Element-UI 首先&#xff0c…

Embeddings原理、使用方法、优缺点、案例以及注意事项

Embeddings是一种将高维数据映射到低维空间的技术,常用于处理自然语言处理(NLP)和计算机视觉(CV)任务。Embeddings可以将复杂的高维数据转换为低维稠密向量,使得数据可以更容易地进行处理和分析。本文将介绍…

张家界(24-17)

目录 总路线酒店:深圳北->张家界西(day1 07:14~13:45)张家界西(酒店)->张家界森林公园东门(day2 早上)张家界森林公园东门->张家界西(day2 19:48分的高铁)张家界…

leetcode-有重复数字的全排列-98

题目要求 思路 1.同【没有重复项的全排列-97】这个题一样,都是递归的题,区别在于这个可能会包含重复的数字,因此,不能只是简单的通过两个值是否相等然后用标志位标记,而是新增了一个数组,这个数组专门用于…

树和二叉树:二叉树的基本运算算法的实现

一.前言 当前版本仅供笔者复盘 二.二叉树 2.1题目 编写一个程序,实现二叉树的基本运算,具体要求如下:(指定示范实例1:图1。指定示范实例2:图2 ) 1,先序遍历输出该树&#xff08…

Qt QInputDialog详解

1.简介 QInputDialog是一个对话框类,用于从用户那里获取一个单一的值。这个值可以是字符串、数字、或者一个列表中的选项。QInputDialog提供了一个方便的方式来快速创建一个输入对话框,无需自己从头开始构建。 QInputDialog支持多种输入类型&#xff1…

【CTF Web】XCTF GFSJ0475 get_post Writeup(HTTP协议+GET请求+POST请求)

get_post X老师告诉小宁同学HTTP通常使用两种请求方法,你知道是哪两种吗? 解法 用 Postman 发送一个 GET 请求,提交一个名为a,值为1的变量。 http://61.147.171.105:65402/?a1用 Postman 发送一个 POST 请求,提交一个名为b,值为…

【吊打面试官系列】Java高并发篇 - 可以直接调用 Thread 类的 run ()方法么?

大家好,我是锋哥。今天分享关于 【可以直接调用 Thread 类的 run ()方法么?】面试题,希望对大家有帮助; 可以直接调用 Thread 类的 run ()方法么? 当然可以。但是如果我们调用了 Thread 的 run()方法,它的行…

自定义指令基本用法

自定义指令基本用法 1.自定义指令案例一:输入框自动聚焦2.自定义指令生命周期和参数-修饰符3.封装全局自定义指令3.1 创建directive目录,创建index.js,创建format-xx文件3.1 main.js文件引入并传入全局对象3.3 组件中引用 自定义指令 Vue可以…

VSCode通过SSH连接虚拟机Ubuntu失败

问题说明 最近使用VSCode通过SSH连接Ubuntu,通过VSCode访问Ubuntu进行项目开发,发现连接失败 在VSCode中进行SSH配置 这些都没有问题,但在进行连接时候出现了问题,如下: 出现了下面这个弹窗 解决方法 发现当…

【c1】数据类型,运算符/循环,数组/指针,结构体,main参数,static/extern,typedef

文章目录 1.数据类型:编译器(compiler)与解释器(interpreter),中文里的汉字和标点符号是两个字节,不能算一个字符(单引号)2.运算符/循环:sizeof/size_t3.数组…

python类型之string上篇

使用单引号 string1 This is a string in single quotes. print(string1)使用双引号 string2 "This is a string in double quotes." print(string2)使用三引号(多行字符串) string3 This is a multi-linestring in triple quotes&#…

在.NET架构的Winform项目中引入“异步编程”思想和技术

在.NET架构的Winform项目中引入“异步编程”思想和技术 一、异步编程引入(1)异步编程引入背景(2)异步编程程序控制流图(3)异步编程前置知识: 二、异步编程demo步骤1:步骤2&#xff1…

Kafka源码分析(五) - Server端 - 基于时间轮的延时组件

系列文章目录 Kafka源码分析-目录 一. 背景 Kafka内部涉及大量的"延时"操作,比如收到PRODUCE请求后可为副本等待一个timeout的时间后再响应客户端。 那我们讨论一个问题:Kafka为什么自己实现了一个延时任务组件,而不直接使用ja…

微信个人号开发api接口-视频号矩阵接口-VIdeosApi

友情链接:VIdeosApi 获取用户主页 接口地址: http://api.videosapi.com/finder/v2/api/finder/userPage 入参 { "appId": "{{appid}}", "lastBuffer": "", "toUserName": "v2_060000231003b2…