搞点多维分析,糙快猛的解决方式就是使用ROLAP(关系型OLAP)了。数据经维度建模后存储在MySQL,ROLAP引擎(比方开源的Mondrian)负责将OLAP请求转化为SQL语句提交给数据库。OLAP计算分析功能导致MySQL须要进行较多复杂SQL查询,性能调优不可缺少,本文总结了一些有用原则。

OLAP特点

OLAP的典型应用包含复杂动态报表,须要支持钻取(上卷和下钻)、切片、切块和旋转操作。下表总结了OLAP和OLTP系统的主要差别。OLAP的特点决定了SQL的查询场景和优化方案,下文将从索引、聚合、子查询、表连接和Pivoting等几个方面分别介绍。

OLAP

OLTP

用户量

分析人员用户量相对小

高并发

数据库设计

维度模型:星型、雪花型号

规范化

数据量

大,动辄千万级别

小,一般不超过百万级别

SQL读写场景

定期导入,一般无更新,复杂查询每次检索大量数据

以事务为单位每次读写少量数据

老生常谈之索引

在权衡数据容错恢复和性能之后,存储引擎选择的是Innodb。Innodb索引的特性是主键聚集索引和B+Tree数据结构。利用这两个特性,可以提升数据导入和多维度组合切片的性能。

1)       数据导入速度

下图为Innodb表主键索引示意图,聚集索引使表中全部数据必须依照主键顺序存储在主键索引叶子节点上。假设不依照主键顺序导入数据,会导致额外的分页、数据查找、移动IO操作,这样,Innodb表的插入速度严重依赖于插入顺序。解决方法比較简单:主键使用Auto_Increment列。

2)       多维度切片

多维度组合查询、分组和汇总操作很常见,那么在多个维度字段上加入复合索引是不可缺少的,而复合索引的字段选择和顺序尤为重要。

谁排NO.1?一般遵循下面原则:

a)        Mysql仅仅进行索引最左前缀匹配,能够选择最常查询的字段排首位。特殊情况:如果少量查询场景不存在该字段怎么处理?须要另外再建索引吗?如果在盘古系统中,运营单位通常会出如今全部查询中,所以会建立[运营单位,行业,产品线……]的复合索引,但某些高级别管理人员的查询语句中,不包括运营单位,那么须要再建立[行业,产品线……]的复合索引吗?答案是看情况,提供小技巧:应用层处理,在不包括运营单位条件的查询SQL中增加“运营单位 in(全部运营单位)”条件

b)        最佳性能优化原则决定索引区分度最大的字段排首位(可用count(distinct column)/count(*)计算)

还有个大家往往会忽略的问题,谁排最后呢?答案是:将可能存在范围条件检索的字段放最后。来个案例

……WHERE avg_csm_weekly >100 AND trade_id= 19 ORDER BY balance如果建立的复合索引为[avg_cms_weekly,trade_id, ,balance],那么因为在avg_csm_weekly上存在范围条件,MySQL不会使用剩余的索引。

聚合

MySQL不支持Hash聚合,仅支持流聚合。流聚合会先依据GROUP BY的字段进行排序,然后流式訪问排序好的数据,进行分组聚合。假设在explain的extra列中看到Using temporary和Using filesort,说明聚合使用了暂时表和文件排序操作,这可能导致性能低下。最佳优化目标是让聚合操作使用Covering Index,即全然不用查询表数据,仅仅在索引上完毕聚合查询。

以下查询语句会使用复合索引[trade_id,product_line_id]

select trade_id,product_line_id,count(*) from data_acct_info_weekly group bytrade_id,product_line_id

观察查询计划,在extra列显示Using index,说明该操作为Covering

Index查询。

在OLAP分析中,时间范围上的聚合操作很普遍。以下以账号每日消费表为演示样例,总结几种常见的时间聚合查询模板

account_id(账户)

stdate(数据日期)

click_pay(点击消费)

1

2013-08-01

100

1

2013-08-02

150

2

2013-08-01

125

1)累计聚合

返回账户增加某度以来累计消费和平均值。

SELECT a.account_id,a.stdate ,SUM(click_pay),AVG(click_pay)

FROM data_account_csm_daily a INNER JOIN data_account_csm_daily b

ON a.account_id=b.account_id ANDb.stdate<=a.stdate

GROUP BY a.account_id,a.stdate

ORDER BY a.account_id,a.stdate

2)滑动累计

返回账户固定窗体时间内累计消费和平均值

SELECT a.account_id,a.stdate ,SUM(click_pay),AVG(click_pay)

FROM data_account_csm_daily a INNER JOIN data_account_csm_daily b

ON a.account_id=b.account_id ANDb.stdate<=a.stdate

AND b.stdate>=DATE_ADD(a.stdate,INTERVAL -30 DAY)

GROUP BY a.account_id,a.stdate

ORDER BY a.account_id,a.stdate

3)MTD累计

返回账户月初以来累计消费和平均值

SELECT a.account_id,a.stdate,SUM(click_pay),AVG(click_pay)

FROM data_account_csm_daily a INNER JOIN data_account_csm_daily b

ON a.account_id=b.account_id ANDb.stdate<=a.stdate

AND b.stdate>=DATE_FORMAT(a.stdate,”%Y-%M-01”)

GROUP BY a.account_id,a.stdate

ORDER BY a.account_id,a.stdate再探讨下ROLLUP和CUBE。如果用户须要对N个维度进行聚合操作,须要进行N次GROUP BY再将结果进行UNION,而使用ROLLUP能够一次查询出N次GROUP BY 操作的结果。以下的两条语句查询结果一致,运行计划上却不同,前者仅仅须要扫描一次,后者则须要扫描表四次。

语句1:

SELECT col1,col2,col3,SUM(col4) FROM table

GROUP BYcol1,col2,col3

WITH ROLLUP语句2:

SELECT col1,col2,col3,SUM(col4) FROM table

GROUP BYcol1,col2,col3

UNION

SELECT col1,col2,NULL,SUM(col4) FROM table

GROUP BYcol1,col2

UNION

SELECT col1,NULL,NULL ,SUM(col4) FROM table

GROUP BY col1

UNION

SELECT NULL,NULL,NULL,SUM(col4) FROM table与ROLLUP仅仅在同一层次上对维度进行汇总不同,CUBE对全部维度进行汇总,N个维度CUBE须要2的N次方分组操作。当前版本号的MySQL还不支持CUBE操作,但和用多个GROUP操作UNION模拟ROLLUP同理,也能够用多个ROLLUP操作UNION模拟CUBE。

子查询vs JOIN

复杂的需求场景导致某些子查询场景不可避免。关于子查询,存在不少性能陷阱和认识误区值得关注。

1)MySQL子查询性能差的主要原因是子查询产生暂时表吗?不全然正确,暂时表并不可怕,一个完整的SQL语句,FROM/JOIN/GROUP/WHERE/ORDER等操作,不考虑索引优化的情况下,都有可能产生暂时表。所以更严格的表述是在子查询产生的暂时表上查询无法利用索引导致性能低下。

2)IN子查询往往性能不佳的真实原因是什么?是IN查询的暂时表数据量太大,MySQL太弱,仅仅能支持极少数量的IN子查询吗?不一定,显示列表IN(a,b,c)查询的性能并不算差,IN子查询真正的性能陷阱在于Mysql优化器往往将IN独立子查询优化成EXISTS相关子查询!所以当观察SELECT * FROM table1 WHERE table1.id IN(SELECT id FROM table2)的查询计划,会发现table2的查询为DEPEDENTSUBQUERY,原因事实上是MySQL优化策略+历史原因。

3)子查询的性能一定弱于JOIN吗?未必,因为Mysql不支持Semi Join(注),所以在某些须要场景下,使用子查询性能优于JOIN。比方A表和B表一对多关系,假设只想查询在B表中存在相应记录的A表记录,假设使用JOIN,须要用DISTINCT或者GROUP操作进行去重操作。使用关联子查询能够避免这部分开销。SELECT id FROM table1 WHERE EXISTS(SELECT table2.id FROM table2WHERE table2.id=table1.id)

关于Join,Mysql使用Nested Loop算法(注)。在典型的星型维度模型中,维度表数据量远小于事实表,JOIN操作往往是大小表连接,性能问题不大,这方面不多讲。结合前面提到的Covering Index,介绍一个利用JOIN提高分页效率的歪招:

分页往往须要用到LIMIT OFFSET,在偏移量非常大的时候,比方LIMIT 100000,50,MySQL须要检索100050数据,性能严重下降。常见的处理方式是a)添加排序辅助列,将LIMIT转化为在辅助列上范围查找操作b)应用层缓存机制c)需求折中,没有人会翻到100000页。以上皆不灵的时候,能够选择Covering

Index+Join。

SELECT * FROM table1 INNER JOIN

(SELECT id FROM table1 ORDER BY indexed_col limit 100000,50) AS a

ON table1.id = a.id这样的方式效率较高,由于暂时表a仅在索引上进行操作(Innodb索引叶子节点上存储了主键值),取得所需行id之后,再和完整的表进行Join获取其它所需列。

注:MySQL的著名分支MarioDB支持Semi

Join和Hash Join

其它

Pivoting&Unpivoting主要关注行列旋转变化,还能够用来对聚合数据进行格式化用于报表展现,在此不再复述

olap mysql_MySQL与OLAP:分析型SQL查询最佳实践探索相关推荐

  1. olap与mysql_MySQL与OLAP:分析型SQL查询最佳实践探索

    搞点多维分析,糙快猛的解决方案就是使用ROLAP(关系型OLAP)了.数据经维度建模后存储在MySQL,ROLAP引擎(比如开源的Mondrian)负责将OLAP请求转化为SQL语句提交给数据库.OL ...

  2. MySQL与OLAP:分析型SQL查询最佳实践探索

    搞点多维分析,糙快猛的解决方式就是使用ROLAP(关系型OLAP)了.数据经维度建模后存储在MySQL,ROLAP引擎(比方开源的Mondrian)负责将OLAP请求转化为SQL语句提交给数据库.OL ...

  3. SQL Server 最佳实践分析器使用小结

    Best Practices Analyzer Tool for Microsoft SQL Server 2000是Microsoft SQL Server开发团队开发的一个数据库管理工具,可以让你 ...

  4. 管理信息系统案例分析_7.软件需求最佳实践笔记 | 需求分析与建模(一)

    一.需求分析与建模的要点与误区 需求分析到底做什么 需求分析的任务并不是分析系统如何实现用户的需要,这是对需求分析最常见的误解.需求分析实际上是业务分析,也就是选择一种业务导向的线索将零散的需求串起米 ...

  5. HandlerThread原理分析、实战、最佳实践!

    本文我们将学习HandlerThread的实现原理,以及开发时,如何正确的使用它来实现我们的开发任务. HandlerThread源码分析 设想这样一个场景:我们要在一个线程A中处理业务逻辑,在另一个 ...

  6. pb 判断sql 是否合法_宜信技术|《SQL优化最佳实践》作者带你重新了解SQL

    一.SQL :一种熟悉又陌生的编程语言 这里有几个关键词:"熟悉"."陌生"."编程语言". 说它"熟悉",是因为它是D ...

  7. Kubernetes Ingress 日志分析与监控的最佳实践

    2019独角兽企业重金招聘Python工程师标准>>> 前言 目前Kubernetes(K8s)已经真正地占领了容器编排市场,是默认的云无关计算抽象,越来越多的企业开始将服务构建在K ...

  8. 流量洪峰成为常态,腾讯数据库如何高性能支撑海量SQL查询?

    今天分享的主题是TDSQL-SQL引擎架构的演进和查询优化实战.今天分享分为四章,分别是:TDSQL简介.SQL引擎简介.SQL引擎查询处理和最佳实践. 点击图片收看直播回放及下载讲师PPT 1. T ...

  9. Kyligence 客户案例“泰康集团精细化经营分析与运营平台”获评数据智能最佳实践案例

    近日,"2022 爱分析·中国数据智能最佳实践案例"评选结果正式揭晓.Kyligence 携手泰康集团申报的"泰康集团精细化经营分析与运营平台"项目经过多轮角逐 ...

最新文章

  1. Java学习笔记:内部类/匿名内部类的全面介绍
  2. python程序代码大全-调试Python程序代码的几种方法总结
  3. c++17(6)-数学 函数
  4. 原生 遍历_前端原生写js代码还是用vue等框架写项目?
  5. Yii获取指定URL路径字符串
  6. 基克的聚合 机器人_重做秒变神器!基克的聚合成辅助标配
  7. js中的引用类型-object
  8. JavaScript数据结构——树(Tree)
  9. RedHat Linux设置yum软件源为本地ISO
  10. LAMP架构调优(三)——模块的安装与调用
  11. php元换成万元,元换算成万元(元与万元的换算器)
  12. 首席新媒体黎想教程:如何执行一场活动策划方案!
  13. Spring Cloud与Dubbo优缺点详解
  14. php gd 坐标,【PHP】GD库笔记 初探GD库的坐标
  15. 【opencv学习笔记】第五篇:访问图像中像素的三种方式、ROI区域图像叠加和图像混合
  16. STC12驱动PCF8575
  17. kalibr使用笔记
  18. mysql的R树_GIS笔记——R树:一种用于空间查找的动态索引结构(算是节译)
  19. <会说话是本事>的记录文摘
  20. 用计算机弹出黎明的黑暗,黎明杀机easyanticheat error怎么解决 跳出easyanticheat error怎么办按...

热门文章

  1. 2个程序员街头卖唱,挽救了自己的秃头
  2. 经典面试题(47):以下代码将输出的结果是什么?
  3. 通俗易懂,先来认识一下Vuex
  4. The Innovation | 中国开启肿瘤CAR-T治疗新时代
  5. Pandoc提供二进制分发包了
  6. Linux 迎来 29 岁:从个人爱好到统治世界的操作系统内核
  7. 中文名称的文件传不到ftp服务器,FTP上传文件时文件的中文名称变为#号,解决方法...
  8. github 公钥 私钥_搭建自己的技术博客系列 2:把 Hexo 博客部署到 GitHub 上
  9. VSCode 代码风格统一设置eslint + stylelint
  10. centos 7 java安装路径_Linux CentOS 7.0中java安装与配置环境变量的步骤详解