【SQL开发实战技巧】系列(二十七):数仓报表场景☞通过对移动范围进行聚集来详解分析函数开窗原理以及如何一个SQL打印九九乘法表

本文涉及的产品
云原生数据仓库AnalyticDB MySQL版,基础版 8ACU 100GB 1个月
简介: 本篇文章讲解的主要内容是:***通过执行计划看开窗函数开窗语法rows\range between preceding and current row以及rows\range between unbounded preceding and unbounded following对移动范围的值进行聚集的原理以及区别】、如何通过一个SQL打印九九乘法口表!!!***

前言

本篇文章讲解的主要内容是:通过执行计划看开窗函数开窗语法rows\range between preceding and current row以及rows\range between unbounded preceding and unbounded following对移动范围的值进行聚集的原理以及区别、如何通过一个SQL打印九九乘法口表!!!
【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。


一、对移动范围的值进行聚集

现在有个需求:要求在员工明细表中显示之前90天(包含90)以内聘用人员的工资总和。
我以部门30为例,在这里给大家标量及分析函数两种方式的写法示例及解释。

SQL> select hiredate,
  2         sal,
  3         (select sum(sal)
  4            from emp aa
  5           where aa.hiredate <= a.hiredate
  6             and aa.hiredate >= (a.hiredate - 90)
  7             and aa.deptno = 30) as 标量求值,
  8         '(' || to_char(hiredate - 90, 'yyyy-mm-dd') || '~' ||
  9         to_char(hiredate, 'yyyy-mm-dd') || ')' as 时间范围,
 10         sum(sal) over(order by hiredate range between 90 preceding and current row) as 分析函数求值,
 11         (select listagg(sal, '+') within group(order by hiredate)
 12            from emp s
 13           where deptno = 30
 14             and s.hiredate >= (a.hiredate - 90)
 15             and s.hiredate <= a.hiredate) as 公式推导
 16    from emp a
 17   where a.deptno = 30;

HIREDATE          SAL       标量求值 时间范围                                                                             分析函数求值 公式推导
----------- --------- ---------- -------------------------------------------------------------------------------- ---------- --------------------------------------------------------------------------------
1981-2-20     1600.00       1600 (1980-11-22~1981-02-20)                                                                1600 1600
1981-2-22     1250.00       2850 (1980-11-24~1981-02-22)                                                                2850 1600+1250
1981-5-1      2850.00       5700 (1981-01-31~1981-05-01)                                                                5700 1600+1250+2850
1981-9-8      1500.00       1500 (1981-06-10~1981-09-08)                                                                1500 1500
1981-9-28     1250.00       2750 (1981-06-30~1981-09-28)                                                                2750 1500+1250
1981-12-3      950.00       3700 (1981-09-04~1981-12-03)                                                                3700 1500+1250+950

6 rows selected

因用RANGE关键字表示要对相应的字段做加减运算,所以只有对日期与数值两类字段使用RANGE开窗。
对于日期RANGE开窗,默认单位是“天”,如果需求改为三个月内的数据呢?我们可以用INTERVAL来写明间隔单位:

SQL> select hiredate,
  2         sal,
  3         sum(sal) over(order by hiredate range between interval '3' month preceding and current row) as 分析函数求值
  4    from emp a
  5   where a.deptno = 30;

HIREDATE          SAL     分析函数求值
----------- --------- ----------
1981-2-20     1600.00       1600
1981-2-22     1250.00       2850
1981-5-1      2850.00       5700
1981-9-8      1500.00       1500
1981-9-28     1250.00       2750
1981-12-3      950.00       3700

6 rows selected

如果按分钟开窗呢?

SQL> select aa.ADDRESS,
  2         count(*) over(order by aa.LAST_ACTIVE_TIME range between interval '30' minute preceding and current row) as interval_cnt,
  3         count(*) over(order by aa.LAST_ACTIVE_TIME range between 30 / 24 / 60 preceding and current row) as ceil_cnt
  4    from v$sql aa
  5   where aa.LAST_ACTIVE_TIME >= trunc(sysdate)
  6   and rownum<=10;

ADDRESS          INTERVAL_CNT   CEIL_CNT
---------------- ------------ ----------
0000000EF7A8E3F0            1          1
0000000F1E29E158            1          1
0000000F18C1C570            2          2
0000000F1A5C9B20            1          1
0000000F1AB3DBB0            1          1
0000000F06D2B370            1          1
0000000F0D8CF5D0            1          1
0000000F06D2B370            1          1
0000000EFCE2BA78            1          1
0000000F0D8CF5D0            1          1

10 rows selected

30 / 24 / 60interval '30' minute都可以,当然后一种更直观。

二、详细分析常用分析函数开窗过程

本节汇总演示分析函数常见的几种用法及区别。
1、工资排序后取第一行到当前行范围内的最小值。

SQL> select ename,
  2         sal,
  3         /*因是按工资排序,所以这个语句返回的结果就是所有行的最小值*/
  4         min(sal) over(order by sal) as min1,
  5         /*上述语句默认参数如下,下面plan中可以看到*/
  6         min(sal) over(order by sal range between unbounded preceding and current row) min2,
  7         /*这种情况卡,rows与RANGE返回数据一样*/
  8         min(sal) over(order by sal rows between unbounded preceding and current row) min3,
  9         /*取所有行内最小值,可以与前面返回的值对比查看*/
 10         min(sal) over() as min4,
 11         /*如果明确写出上面min14的范围就是*/
 12         min(sal) over(order by sal range between unbounded preceding and unbounded following) as min5,
 13         /*这种情况下,rows与RANGE返回数据一样*/
 14         min(sal) over(order by sal rows between unbounded preceding and unbounded following) as min6
 15    from emp
 16   where deptno = 30;

ENAME            SAL       MIN1       MIN2       MIN3       MIN4       MIN5       MIN6
---------- --------- ---------- ---------- ---------- ---------- ---------- ----------
JAMES         950.00        950        950        950        950        950        950
WARD         1250.00        950        950        950        950        950        950
MARTIN       1250.00        950        950        950        950        950        950
TURNER       1500.00        950        950        950        950        950        950
ALLEN        1600.00        950        950        950        950        950        950
BLAKE        2850.00        950        950        950        950        950        950

6 rows selected


SQL> 

为了看到上面 min(sal) over(order by sal) as min1在执行计划中到底是转译成了什么语句,这里专门改写成一个独立sql后,然后拿到的实际执行计划:

SQL> set linesize 200
set pagesize 2000
select * from table(dbms_xplan.display_cursor('&A',0,'advanced'));
SQL> SQL> Enter value for a: 5pffdrwf22rk8
old   1: select * from table(dbms_xplan.display_cursor('&A',0,'advanced'))
new   1: select * from table(dbms_xplan.display_cursor('5pffdrwf22rk8',0,'advanced'))

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID    5pffdrwf22rk8, child number 0
-------------------------------------
select /*12345*/ ename,        sal,
/*因按工资排序,所以这个语句与上面sal返回的值一样*/     min(sal) over(order by sal) as min1
 from emp  where deptno = :"SYS_B_0"

Plan hash value: 3145491563

---------------------------------------------------------------------------
| Id  | Operation       | Name | Rows  | Bytes | Cost (%CPU)| Time      |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      |      |    4 (100)|      |
|   1 |  WINDOW SORT       |      |    6 |    78 |    4  (25)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| EMP  |    6 |    78 |    3   (0)| 00:00:01 |
---------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   2 - SEL$1 / EMP@SEL$1

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.1.0.2')
      DB_VERSION('12.1.0.2')
      OPT_PARAM('_b_tree_bitmap_plans' 'false')
      OPT_PARAM('_bloom_filter_enabled' 'false')
      OPT_PARAM('_optimizer_extended_cursor_sharing' 'none')
      OPT_PARAM('_gby_hash_aggregation_enabled' 'false')
      OPT_PARAM('_optimizer_extended_cursor_sharing_rel' 'none')
      OPT_PARAM('_optimizer_adaptive_cursor_sharing' 'false')
      OPT_PARAM('_optimizer_use_feedback' 'false')
      OPT_PARAM('_optimizer_unnest_scalar_sq' 'false')
      OPT_PARAM('_px_adaptive_dist_method' 'off')
      OPT_PARAM('_optimizer_dsdir_usage_control' 0)
      OPT_PARAM('_optimizer_adaptive_plans' 'false')
      OPT_PARAM('_optimizer_strans_adaptive_pruning' 'false')
      OPT_PARAM('_optimizer_null_accepting_semijoin' 'false')
      OPT_PARAM('_optimizer_gather_feedback' 'false')
      OPT_PARAM('_optimizer_aggr_groupby_elim' 'false')
      OPT_PARAM('_optimizer_reduce_groupby_key' 'false')
      OPT_PARAM('_optimizer_nlj_hj_adaptive_join' 'false')
      OPT_PARAM('_fix_control' '8611462:0 14826303:0')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "EMP"@"SEL$1")
      END_OUTLINE_DATA
  */

Peeked Binds (identified by position):
--------------------------------------

   1 - :SYS_B_0 (NUMBER): 30

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("DEPTNO"=:SYS_B_0)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=1) "SAL"[NUMBER,22], "ENAME"[VARCHAR2,10],
       "DEPTNO"[NUMBER,22], MIN("SAL") OVER ( ORDER BY "SAL" RANGE  BETWEEN
       UNBOUNDED  PRECEDING  AND  CURRENT ROW )[22]
   2 - "ENAME"[VARCHAR2,10], "SAL"[NUMBER,22], "DEPTNO"[NUMBER,22]


72 rows selected.

从上面执行计划能够看到, min(sal) over(order by sal)实际改写成了

MIN("SAL") OVER ( ORDER BY "SAL" RANGE  BETWEEN
       UNBOUNDED  PRECEDING  AND  CURRENT ROW )[22]

2、工资排序后取第一行到当前行范围内的最大值。

SQL> select ename,
  2         sal,
  3         /*因按工资排序,所以这个语句与上面sal返回的值一样*/
  4         max(sal) over(order by sal) as max1,
  5         /*上述语句默认参数如下,plan中可以看到*/
  6         MAX(sal) over(order by sal range between unbounded preceding and current row) MAX2,
  7         /*这种情况卡,rows与RANGE返回数据一样*/
  8         MAX(sal) over(order by sal rows between unbounded preceding and current row) MAX3,
  9         /*取所有行的内最大值,可以与前面返回的值对比查看*/
 10         MAX(sal) over() as MAX4,
 11         /*如果明确写出上面MAX4的范围就是*/
 12         MAX(sal) over(order by sal range between unbounded preceding and unbounded following) as MAX5,
 13         /*这种情况下,rows与RANGE返回数据一样*/
 14         MAX(sal) over(order by sal rows between unbounded preceding and unbounded following) as MAX6
 15    from emp
 16   where deptno = 30;

ENAME            SAL       MAX1       MAX2       MAX3       MAX4       MAX5       MAX6
---------- --------- ---------- ---------- ---------- ---------- ---------- ----------
JAMES         950.00        950        950        950       2850       2850       2850
WARD         1250.00       1250       1250       1250       2850       2850       2850
MARTIN       1250.00       1250       1250       1250       2850       2850       2850
TURNER       1500.00       1500       1500       1500       2850       2850       2850
ALLEN        1600.00       1600       1600       1600       2850       2850       2850
BLAKE        2850.00       2850       2850       2850       2850       2850       2850

6 rows selected

为了看到上面 max(sal) over(order by sal) as max1在执行计划中到底是转译成了什么语句,这里专门改写成一个独立sql后,然后拿到的实际执行计划:

select * from table(dbms_xplan.display_cursor('&A',0,'advanced'));
SQL> SQL> Enter value for a: 5snuncy0dcrhf
old   1: select * from table(dbms_xplan.display_cursor('&A',0,'advanced'))
new   1: select * from table(dbms_xplan.display_cursor('5snuncy0dcrhf',0,'advanced'))

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID    5snuncy0dcrhf, child number 0
-------------------------------------
select /*12345*/ ename,        sal,
/*因按工资排序,所以这个语句与上面sal返回的值一样*/       max(sal) over(order by sal) as
max1   from emp  where deptno = :"SYS_B_0"


Plan hash value: 3145491563

---------------------------------------------------------------------------
| Id  | Operation       | Name | Rows  | Bytes | Cost (%CPU)| Time      |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      |      |    4 (100)|      |
|   1 |  WINDOW SORT       |      |    6 |    78 |    4  (25)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| EMP  |    6 |    78 |    3   (0)| 00:00:01 |
---------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1
   2 - SEL$1 / EMP@SEL$1

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('12.1.0.2')
      DB_VERSION('12.1.0.2')
      OPT_PARAM('_b_tree_bitmap_plans' 'false')
      OPT_PARAM('_bloom_filter_enabled' 'false')
      OPT_PARAM('_optimizer_extended_cursor_sharing' 'none')
      OPT_PARAM('_gby_hash_aggregation_enabled' 'false')
      OPT_PARAM('_optimizer_extended_cursor_sharing_rel' 'none')
      OPT_PARAM('_optimizer_adaptive_cursor_sharing' 'false')
      OPT_PARAM('_optimizer_use_feedback' 'false')
      OPT_PARAM('_optimizer_unnest_scalar_sq' 'false')
      OPT_PARAM('_px_adaptive_dist_method' 'off')
      OPT_PARAM('_optimizer_dsdir_usage_control' 0)
      OPT_PARAM('_optimizer_adaptive_plans' 'false')
      OPT_PARAM('_optimizer_strans_adaptive_pruning' 'false')
      OPT_PARAM('_optimizer_null_accepting_semijoin' 'false')
      OPT_PARAM('_optimizer_gather_feedback' 'false')
      OPT_PARAM('_optimizer_aggr_groupby_elim' 'false')
      OPT_PARAM('_optimizer_reduce_groupby_key' 'false')
      OPT_PARAM('_optimizer_nlj_hj_adaptive_join' 'false')
      OPT_PARAM('_fix_control' '8611462:0 14826303:0')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "EMP"@"SEL$1")
      END_OUTLINE_DATA
  */

Peeked Binds (identified by position):
--------------------------------------

   1 - :SYS_B_0 (NUMBER): 30

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("DEPTNO"=:SYS_B_0)

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=1) "SAL"[NUMBER,22], "ENAME"[VARCHAR2,10],
       "DEPTNO"[NUMBER,22], MAX("SAL") OVER ( ORDER BY "SAL" RANGE  BETWEEN
       UNBOUNDED  PRECEDING  AND  CURRENT ROW )[22]
   2 - "ENAME"[VARCHAR2,10], "SAL"[NUMBER,22], "DEPTNO"[NUMBER,22]


72 rows selected.

从上面执行计划能够看到,max(sal) over(order by sal)实际改写成了

MAX("SAL") OVER ( ORDER BY "SAL" RANGE  BETWEEN
       UNBOUNDED  PRECEDING  AND  CURRENT ROW )[22]

3、工资排序后取第一行到当前行范围内的工资和,这里要注意区别。

SQL> select ename,
  2         sal,
  3         /*累加工资,要注意工资重复时的现象*/
  4         sum(sal) over(order by sal) as sum1,
  5         /*上述语句默认参数如下,在PLAN中可以看到*/
  6         sum(sal) over(order by sal range between unbounded preceding and current row) as sum2,
  7         /*这种情况卡,rows与RANGE返回数据不一样,见第二行*/
  8         sum(sal) over(order by sal rows between unbounded preceding and current row) as sum3,
  9         /*工资合计*/
 10         sum(sal) over() as sum4,
 11         /*如果明确写出上面sum4的范围就是*/
 12         sum(sal) over(order by sal range between unbounded preceding and unbounded following) as sum5,
 13         /*这种情况下,rows与RANGE返回数据一样*/
 14         sum(sal) over(order by sal rows between unbounded preceding and unbounded following) as sum6
 15    from emp
 16   where deptno = 30;

ENAME            SAL       SUM1       SUM2       SUM3       SUM4       SUM5       SUM6
---------- --------- ---------- ---------- ---------- ---------- ---------- ----------
JAMES         950.00        950        950        950       9400       9400       9400
WARD         1250.00       3450       3450       2200       9400       9400       9400
MARTIN       1250.00       3450       3450       3450       9400       9400       9400
TURNER       1500.00       4950       4950       4950       9400       9400       9400
ALLEN        1600.00       6550       6550       6550       9400       9400       9400
BLAKE        2850.00       9400       9400       9400       9400       9400       9400

6 rows selected

因为使用关键字"RANGE"时,第二行"SUM1"、"SUM2"对应的条件是"<=1250",
而1250有两个,所以会计算两次,产生结果为:950+1250+1250=3450。而"SUM3"不同,它只计算到当前行,所以结果是950+1250=2200。

4、前后都有限定条件。

SQL> select ename,
  2         sal,
  3         /*当前行(+-1500)范围内的最大值*/
  4         max(sal) over(order by sal range between 500 preceding and 500 following) as max1,
  5         /*前后各一行,共三行中的最大值*/
  6         sum(sal) over(order by sal rows between 1 preceding and 1 following) as sum3
  7    from emp
  8   where deptno = 30;

ENAME            SAL       MAX1       SUM3
---------- --------- ---------- ----------
JAMES         950.00       1250       2200
WARD         1250.00       1600       3450
MARTIN       1250.00       1600       4000
TURNER       1500.00       1600       4350
ALLEN        1600.00       1600       5950
BLAKE        2850.00       2850       4450

6 rows selected

三、使用Listagg一个SQL打印九九乘法表

现在有个需求:要求你用一条SQL打印一个九九乘法口诀!!
是不是有点懵逼啊,在其他语言中,这也是一个经常见的面试笔试题,那么用SQL怎么实现呢?
下面可以用listagg的分类汇总功能来实现!
首先要生成基础数据:

SQL> 
SQL> with t as (
  2  select level as lv from dual connect by level<=9
  3  )
  4  select * from t;

        LV
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9

9 rows selected

然后根据这个数据做一下枚举:

SQL> with t as (
  2  select level as lv from dual connect by level<=9
  3  ),
  4  t1 as (
  5  select a.lv la,b.lv lb,b.lv||'*'||a.lv||'='||rpad(a.lv*b.lv,2,' ') as txt
  6  from t a,t b
  7  where b.lv<=a.lv)
  8  select * from t1;

        LA         LB TXT
---------- ---------- --------------------------------------------------------------------------------
         1          1 1*1=1
         2          1 1*2=2
         2          2 2*2=4
         3          1 1*3=3
         3          2 2*3=6
         3          3 3*3=9
         4          1 1*4=4
         4          2 2*4=8
         4          3 3*4=12
         4          4 4*4=16
         5          1 1*5=5
         5          2 2*5=10
         5          3 3*5=15
         5          4 4*5=20
         5          5 5*5=25
         6          1 1*6=6
         6          2 2*6=12
         6          3 3*6=18
         6          4 4*6=24
         6          5 5*6=30
         6          6 6*6=36
         7          1 1*7=7
         7          2 2*7=14
         7          3 3*7=21
         7          4 4*7=28
         7          5 5*7=35
         7          6 6*7=42
         7          7 7*7=49
         8          1 1*8=8
         8          2 2*8=16
         8          3 3*8=24
         8          4 4*8=32
         8          5 5*8=40
         8          6 6*8=48
         8          7 7*8=56
         8          8 8*8=64
         9          1 1*9=9
         9          2 2*9=18
         9          3 3*9=27
         9          4 4*9=36
         9          5 5*9=45
         9          6 6*9=54
         9          7 7*9=63
         9          8 8*9=72
         9          9 9*9=81

45 rows selected


SQL> 

最后用listagg分类汇总,把LA相同的数据合并为一行:

SQL> with t as (
  2  select level as lv from dual connect by level<=9
  3  ),
  4  t1 as (
  5  select a.lv la,b.lv lb,b.lv||'*'||a.lv||'='||rpad(a.lv*b.lv,2,' ') as txt
  6  from t a,t b
  7  where b.lv<=a.lv)
  8  select listagg(txt,' ')within group(order by t1.la) as 九九乘法口诀
  9  from t1
 10  group by la;

九九乘法口诀
--------------------------------------------------------------------------------
1*1=1
1*2=2  2*2=4
1*3=3  2*3=6  3*3=9
1*4=4  2*4=8  3*4=12 4*4=16
1*5=5  2*5=10 3*5=15 4*5=20 5*5=25
1*6=6  2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7  2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8  2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9  2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81

9 rows selected

这就达到了我们的目的,可以看到,其实实现起来并不复杂,就是需要思考一下逻辑。


总结

本篇文章讲解的主要内容是:通过执行计划看开窗函数开窗语法rows\range between preceding and current row以及rows\range between unbounded preceding and unbounded following对移动范围的值进行聚集的原理以及区别】、如何通过一个SQL打印九九乘法口表!!!

相关实践学习
阿里云云原生数据仓库AnalyticDB MySQL版 使用教程
云原生数据仓库AnalyticDB MySQL版是一种支持高并发低延时查询的新一代云原生数据仓库,高度兼容MySQL协议以及SQL:92、SQL:99、SQL:2003标准,可以对海量数据进行即时的多维分析透视和业务探索,快速构建企业云上数据仓库。 了解产品 https://www.aliyun.com/product/ApsaraDB/ads
相关文章
|
3月前
|
存储 SQL 关系型数据库
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
|
3月前
|
存储 SQL 监控
数据中台架构解析:湖仓一体的实战设计
在数据量激增的数字化时代,企业面临数据分散、使用效率低等问题。数据中台作为统一管理与应用数据的核心平台,结合湖仓一体架构,打通数据壁垒,实现高效流转与分析。本文详解湖仓一体的设计与落地实践,助力企业构建统一、灵活的数据底座,驱动业务决策与创新。
|
28天前
|
存储 自然语言处理 分布式计算
Apache Doris 3.1 正式发布:半结构化分析全面升级,湖仓一体能力再跃新高
Apache Doris 3.1 正式发布!全面升级半结构化分析,支持 VARIANT 稀疏列与模板化 Schema,提升湖仓一体能力,增强 Iceberg/Paimon 集成,优化存储引擎与查询性能,助力高效数据分析。
262 4
Apache Doris 3.1 正式发布:半结构化分析全面升级,湖仓一体能力再跃新高
|
7月前
|
分布式计算 运维 监控
Dataphin离线数仓搭建深度测评:数据工程师的实战视角
作为一名金融行业数据工程师,我参与了阿里云Dataphin智能研发版的评测。通过《离线数仓搭建》实践,体验了其在数据治理中的核心能力。Dataphin在环境搭建、管道开发和任务管理上显著提效,如测试环境搭建从3天缩短至2小时,复杂表映射效率提升50%。产品支持全链路治理、智能提效和架构兼容,帮助企业降低40%建设成本,缩短60%需求响应周期。建议加强行业模板库和移动适配功能,进一步提升使用体验。
|
2月前
|
SQL 存储 运维
Apache Doris 在菜鸟的大规模湖仓业务场景落地实践
本文介绍了 Apache Doris 在菜鸟的大规模落地的实践经验,菜鸟为什么选择 Doris,以及 Doris 如何在菜鸟从 0 开始,一步步的验证、落地,到如今上万核的规模,服务于各个业务线,Doris 已然成为菜鸟 OLAP 数据分析的最优选型。
195 2
Apache Doris 在菜鸟的大规模湖仓业务场景落地实践
|
6月前
|
SQL 安全 关系型数据库
SQL注入之万能密码:原理、实践与防御全解析
本文深入解析了“万能密码”攻击的运行机制及其危险性,通过实例展示了SQL注入的基本原理与变种形式。文章还提供了企业级防御方案,包括参数化查询、输入验证、权限控制及WAF规则配置等深度防御策略。同时,探讨了二阶注入和布尔盲注等新型攻击方式,并给出开发者自查清单。最后强调安全防护需持续改进,无绝对安全,建议使用成熟ORM框架并定期审计。技术内容仅供学习参考,严禁非法用途。
928 0
|
3月前
|
存储 传感器 数据采集
什么是实时数仓?实时数仓又有哪些应用场景?
实时数仓是一种能实现秒级数据更新和分析的系统,适用于电商、金融、物流等需要快速响应的场景。相比传统数仓,它具备更高的时效性和并发处理能力,能够帮助企业及时捕捉业务动态,提升决策效率。本文详细解析了其实现架构与核心特点,并结合实际案例说明其应用价值。
|
3月前
|
SQL DataWorks 关系型数据库
DataWorks+Hologres:打造企业级实时数仓与高效OLAP分析平台
本方案基于阿里云DataWorks与实时数仓Hologres,实现数据库RDS数据实时同步至Hologres,并通过Hologres高性能OLAP分析能力,完成一站式实时数据分析。DataWorks提供全链路数据集成与治理,Hologres支持实时写入与极速查询,二者深度融合构建离在线一体化数仓,助力企业加速数字化升级。
|
5月前
|
存储 缓存 分布式计算
StarRocks x Iceberg:云原生湖仓分析技术揭秘与最佳实践
本文将深入探讨基于 StarRocks 和 Iceberg 构建的云原生湖仓分析技术,详细解析两者结合如何实现高效的查询性能优化。内容涵盖 StarRocks Lakehouse 架构、与 Iceberg 的性能协同、最佳实践应用以及未来的发展规划,为您提供全面的技术解读。 作者:杨关锁,北京镜舟科技研发工程师
StarRocks x Iceberg:云原生湖仓分析技术揭秘与最佳实践
|
7月前
|
SQL 分布式计算 数据挖掘
从湖仓分离到湖仓一体,四川航空基于 SelectDB 的多源数据联邦分析实践
川航选择引入 SelectDB 建设湖仓一体大数据分析引擎,取得了数据导入效率提升 3-6 倍,查询分析性能提升 10-18 倍、实时性提升至 5 秒内等收益。
509 63
从湖仓分离到湖仓一体,四川航空基于 SelectDB 的多源数据联邦分析实践

热门文章

最新文章