数据挖掘目前在各类企业和机构中蓬勃发展。因此我们制作了一份此领域常见术语总结。
数据库与数据仓库的区别实际讲的是 OLTP 与 OLAP 的区别。
操作型处理,叫联机事务处理 OLTP(On-Line Transaction Processing,),也可以称面向交易的处理系统,它是针对具体业务在数据库联机的日常操作,通常对少数记录进行查询、修改。用户较为关心操 作的响应时间、数据的安全性、完整性和并发支持的用户数等问题。传统的数据库系统作为数据管理的 主要手段,主要用于操作型处理。
分析型处理,叫联机分析处理 OLAP(On-Line Analytical Processing) 一般针对某些主题的历史数据进行分析,支持管理决策。
首先要明白,数据仓库的出现,并不是要取代数据库。
以银行业务为例。数据库是事务系统的数据平台,客户在银行做的每笔交易都会写入数据库,被记录下 来,这里,可以简单地理解为用数据库记账。数据仓库是分析系统的数据平台,它从事务系统获取数 据,并做汇总、加工,为决策者提供决策的依据。比如,某银行某分行一个月发生多少交易,该分行当 前存款余额是多少。如果存款又多,消费交易又多,那么该地区就有必要设立ATM了。
显然,银行的交易量是巨大的,通常以百万甚至千万次来计算。事务系统是实时的,这就要求时效性, 客户存一笔钱需要几十秒是无法忍受的,这就要求数据库只能存储很短一段时间的数据。而分析系统是 事后的,它要提供关注时间段内所有的有效数据。这些数据是海量的,汇总计算起来也要慢一些,但 是,只要能够提供有效的分析数据就达到目的了。
数据仓库,是在数据库已经大量存在的情况下,为了进一步挖掘数据资源、为了决策需要而产生的,它 决不是所谓的“大型数据库”。
相关概念
数据仓库: 即DW完整英文名为Data Warehouse,它是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理决策。
多维数据集: 多维数据集是联机分析处理 (OLAP) 中的主要对象,是一项可对数据仓库中的数据进行快速访问的技术.多维数据集是一个数据集合,通常从数据仓库的子集构造,并组织和汇总成一个由一组维度和度量值定义的多维结构.
维度:多维数据集的结构性特性.它们是事实数据表中用来描述数据的分类的有组织层次结构(级别).这些分类和级别描述了一些相似的成员集合,用户将基于这些成员集合进行分析.
度量值: 在多维数据集中,度量值是一组值,这些值基于多维数据集的事实数据表中的一列,而且通常为数字.此外,度量值是所分析的多维数据集的中心值
事实表:是指其中保存了大量业务度量数据的表。事实表中的度量值一般称为事实
其它相关概念详见博客里的介绍,详见 基于mondrian的多维分析系统
ETL:抽取、转换、加载
ETL工作的实质就是从各个数据源提取数据,对数据进行转换,并最终加载填充数据到数据仓库维度建模后的表中。只有当这些维度/事实表被填充好,ETL工作才算完成。接下来分别对抽取,转换,加载这三个环节进行讲解:
1. 抽取(Extract)
数据仓库是面向分析的,而操作型数据库是面向应用的。显然,并不是所有用于支撑业务系统的数据都有拿来分析的必要。因此,该阶段主要是根据数据仓库主题、主题域确定需要从应用数据库中提取的数。
具体开发过程中,开发人员必然经常发现某些ETL步骤和数据仓库建模后的表描述不符。这时候就要重新核对、设计需求,重新进行ETL。正如数据库系列的这篇中讲到的,任何涉及到需求的变动,都需要重头开始并更新需求文档。
2. 转换(Transform)
转换步骤主要是指对提取好了的数据的结构进行转换,以满足目标数据仓库模型的过程。此外,转换过程也负责数据质量工作,这部分也被称为数据清洗(data cleaning)。
3. 加载(Load)
加载过程将已经提取好了,转换后保证了数据质量的数据加载到目标数据仓库。加载可分为两种L:首次加载(first load)和刷新加载(refresh load)。其中,首次加载会涉及到大量数据,而刷新加载则属于一种微批量式的加载。
多说一句,如今随着各种分布式、云计算工具的兴起,ETL实则变成了ELT。就是业务系统自身不会做转换工作,而是在简单的清洗后将数据导入分布式平台,让平台统一进行清洗转换等工作。这样做能充分利用平台的分布式特性,同时使业务系统更专注于业务本身。
OLAP/BI工具
数据仓库建设好以后,用户就可以编写SQL语句对其进行访问并对其中数据进行分析。但每次查询都要编写SQL语句的话,未免太麻烦,而且对维度建模数据进行分析的SQL代码套路比较固定。于是,便有了OLAP工具,它专用于维度建模数据的分析。而BI工具则是能够将OLAP的结果以图表的方式展现出来,它和OLAP通常出现在一起。(注:本文所指的OLAP工具均指代这两者。)
在规范化数据仓库中OLAP工具和数据仓库的关系大致是这样的:
这种情况下,OLAP不允许访问中心数据库。一方面中心数据库是采取规范化建模的,而OLAP只支持对维度建模数据的分析;另一方面规范化数据仓库的中心数据库本身就不允许上层开发人员访问。而在维度建模数据仓库中,OLAP/BI工具和数据仓库的关系则是这样的:
2.3 查询案例
#Sample 1 维度表查询:
SELECT TOP (10) [DateKey] '日期Key'
,[FullDateAlternateKey] '日期代理key'
,[DayNumberOfWeek] '周所在日'
,[EnglishDayNameOfWeek] '所在周'
,[DayNumberOfMonth] '月所在日'
,[DayNumberOfYear] '年所在日'
,[WeekNumberOfYear] '年所在周'
,[EnglishMonthName] '英文月名'
,[MonthNumberOfYear] '年所在月'
,[CalendarQuarter] '所在季度'
,[CalendarYear] '日历年'
,[FiscalQuarter] '财季度'
,[FiscalYear] '财年'
FROM [AdventureWorksDW2019].[dbo].[DimDate]
ORDER BY DateKey DESC
#Sample 2 事实表查询
# 查看2013财年网上销售的产品名、汇率名、订单日期、用户信息、销售额、总产品成本、打折量等。
SELECT TOP 10、 B.EnglishProductName,C.CurrencyName CurrencyName,
D.FrenchPromotionName FrenchPromotionName,E.FirstName,E.LastName,
A.Salesamount,A.TaxAmt,A.TotalProductCost,A.DiscountAmount
FROM FactInternetSales A
JOIN DimProduct B
ON A.ProductKey = B.ProductKey
JOIN DimCurrency C
ON A.CurrencyKey = C.CurrencyKey
JOIN DimPromotion D
ON A.PromotionKey = D.PromotionKey
JOIN DimCustomer E
ON A.CustomerKey = E.CustomerKey
JOIN DimDate F
ON A.OrderDateKey =F.DateKey
WHERE F.FiscalYear=2013
————————————————
0 术语与约束
Extraction-Transformation-Loading 是对OLTP数据进行抽取,转换,装载的过程(以下皆简称ETL)
文档的说明均按照ETL→DW→CUBE→presentation
1 ETL相关
1.1.1时间维度
说明:该维度记录了每天的时间,粒度最高精确到日,并可分周,月,年等粒度.
对应表:tbl_dimdate
对应过程: pro_supportdw_dimdate
是否公用:是
说明:此维度可建Hierarchy(层),见下图:
1.1.2设备维度
说明:该维度记录了的设备信息. 并可分品牌,机型等粒度.
对应表: tbl_dimdevice
对应过程: pro_supportdw_dimdevice
是否公用:否
说明:此维度可建Hierarchy(层),见下图:
1.1.3地域维度
说明:该维度记录了的地域信息. 并可分国家,省,区等粒度.
对应表: tbl_dimgeography
对应过程: 无,必要时手动加入地区数据
是否公用:否
说明:此维度无Hierarchy(层) ,见下图:
1.1.4分辨率维度
说明:该维度记录了分辨率的信息.
对应表: tbl_dimresolution
对应过程: pro_supportdw_dimresolution
是否公用:否
说明:此维度无Hierarchy(层),仅有Level(级别)
1.1.5操作系统维度
说明:该维度记录了的操作系统的信息.
对应表: tbl_dimos
对应过程: pro_supportdw_dimos
是否公用:否
说明:此维度无Hierarchy(层),仅有Level(级别)
1.1.6网络类型维度
说明:该维度记录了网络类型的信息.
对应表: tbl_dimnetworktype
对应过程: 无,手动维护数据
是否公用:否
说明:此维度无Hierarchy(层),仅有Level(级别)
1.1.7运营商维度
说明:该维度记录了运营商类型的信息.
对应表: tbl_dimoperator
对应过程: 无,手动维护数据
是否公用:否
说明:此维度无Hierarchy(层),仅有Level(级别)
1.1.8系统维度
说明:该维度记录了的系统(类似项目 market[市场],桌面[LAU])信息)的信息.
对应表: tbl_dimsystem
对应过程: 无,手动维护数据
是否公用:是
说明:此维度无Hierarchy(层),仅有Level(级别)
1.1.9包维度
说明:该维度记录了包的信息.
对应表: tbl_cms_apk_package_ref
对应过程: 无,手动维护数据,来源于tbl_cms_apk_package(需做数据同步)
是否公用:是
说明:此维度无Hierarchy(层),仅有Level(级别)
1.1.10厂商维度
说明:该维度记录了厂商的信息.
对应表: tbl_user
对应过程: 无
是否公用:是
说明:此维度无Hierarchy(层),仅有Level(级别)
1.1.11系统版本维度
说明:该维度记录了系统的版本信息.
对应表: tbl_dimappversion
对应过程: pro_supportdw_dimappversion
是否公用:是
说明:此维度无Hierarchy(层),仅有Level(级别)
1.1.12广告资源维度
说明:该维度记录了资源或则广告的信息.
对应表: tbl_dimresource
对应过程: 无,手动维护数据,来源于tbl_resource (需做数据同步)
是否公用: 否,广告资源模型独有
说明:此维度无Hierarchy(层),仅有Level(级别)
1.1.13广告资源区分维度
说明:该维度记录了资源或广告区分的信息.
对应表: tbl_dimadres_type
对应过程: 无,手动维护数据
是否公用: 否,广告资源模型独有
说明:此维度无Hierarchy(层),仅有Level(级别)
1.1.14广告资源新旧区分维度
说明:该维度记录了资源或广告区分的信息.
对应表: tbl_dimnewold
对应过程: 无,手动维护数据
是否公用: 否,广告资源模型独有
说明:此维度无Hierarchy(层),仅有Level(级别)
1.1.15系统类型维度
说明:该维度记录了系统子类型(类似airpush类型,uubao类型)的信息
对应表: tbl_dimsystemtype
对应过程: 无,手动维护数据
是否公用: 否,广告资源模型独有
说明:此维度无Hierarchy(层),仅有Level(级别)
1.1.16系统来源维度
说明:该维度记录了系统的来源类型(来源类似广告资源,人工采编)的信息
对应表: tbl_dimresourcetype
对应过程: 无,手动维护数据
是否公用: 否,广告资源模型独有
说明:此维度无Hierarchy(层),仅有Level(级别)
1.2.1 Market事实表与measure(度量)
1.2.1.1 market事实表
TBL_FACTMARKET 该表为market事实表,含有的指标有新增,独立用户,启动次数,留存等.维度精确到IMEI
TBL_FACTMARKET_FIN该表为维度精确到APK_ID
1.2.1.2 market measure(度量)
新增: Market新增用户数量统计
独立: Market独立用户数量统计
启动: Market启动量统计
隔1天market用户留存,此为postUpdate
隔7天market用户留存,此为postUpdate
隔15天market用户留存,此为postUpdate
隔21天market用户留存,此为postUpdate
隔30天market用户留存,此为postUpdate
周留存率
月留存率
1.2.2 广告资源事实表与measure(度量)
1.2.2.1 广告资源事实表
TBL_FACTADRES该表为广告资源事实表,含有的指标有接收,阅读,下载,下载完成,安装等.维度精确到IMEI
TBL_FACTADRES_FIN该表为广告资源事实表,含有的指标有,阅读,点击,下载,下载完成,安装等.维度精确到APK_ID
1.2.2.2 广告资源measure(度量)
接收: 广告资源的接收量统计
阅读量: 广告资源的阅读量统计
下载量: 广告资源的下载量统计
下载完成量: 广告资源的下载完成量统计
安装量: 广告资源的安装量统计
1.3.1 Market模型
pro_supportdw_factmarketmarket2.0以上事实表抽取
pro_support_oldfactmarketmarket1.2版本事实表抽取(含airpush)
pro_supportdw_loadfactmarketmarket事实表抽取汇总(聚合至apk_id维度)
pro_supportdw_preservemarket2.0留存抽取 (此为PostUpdate)
1.3.2 广告资源模型
1.3.3 厂商模型
1.4.1 维度表job
Job对应过程:pro_supportDW_Dim_jobs
包含维度表过程如下:
pro_supportdw_dimdevice(sysdate);–设备维度(设计品牌机型)
pro_supportdw_dimos(sysdate); --操作系统维度
pro_supportdw_dimresolution(SYSDATE);–分辨率维度
pro_new_user_install(SYSDATE); --新用户信息,AdRes对照新旧用户时用
pro_supportdw_dimresource; ---- 新加广告维度数据更新
1.4.2 事实表job
1.4.2.1 market job
market Job对应过程: PRO_Support_Market_JOBs
包含事实表表过程如下:
pro_supportdw_factmarket
pro_support_oldfactmarket
pro_supportdw_loadfactmarket
1.4.2.2 广告资源 job
1.4.2.3 厂商job
厂商Job对应过程: pro_support_adres_agg_jobs
包含事实表表过程如下:
pro_supportdw_factadres
pro_supportdw_loadaggrmarket
2.1 Cube介绍
2.1.1 cube说明
An OLAPcube is an array of data understood in termsof its 0 or more dimensions.
Cube是一个多维数据模型的简称.
2.1.1 cube相关术语
1)多维数据集: 多维数据集是联机分析处理 (OLAP) 中的主要对象,是一项可对数据仓库中的数据进行快速访问的技术.多维数据集是一个数据集合,通常从数据仓库的子集构造,并组织和汇总成一个由一组维度和度量值定义的多维结构.
2)维度: 是多维数据集的结构性特性.它们是事实数据表中用来描述数据的分类的有组织层次结构(级别).这些分类和级别描述了一些相似的成员集合,用户将基于这些成员集合进行分析.
3.度量值: 在多维数据集中,度量值是一组值,这些值基于多维数据集的事实数据表中的一列,而且通常为数字.此外,度量值是所分析的多维数据集的中心值.即,度量值是最终用户浏览多维数据集时重点查看的数字数据.您所选择的度量值取决于最终用户所请求的信息类型.一些常见的度量值有 sales、cost、expenditures 和 production count 等.
4)元数据: 不同 OLAP 组件中的数据和应用程序的结构模型.元数据描述 OLTP 数据库中的表、数据仓库和数据集市中的多维数据集这类对象,还记录哪些应用程序引用不同的记录块.
5)级别: 级别是维度层次结构的一个元素.级别描述了数据的层次结构,从数据的最高(汇总程度最大)级别直到最低(最详细)级别.
6)数据挖掘: 数据挖掘使您得以定义包含分组和预测规则的模型,以便应用于关系数据库或多维 OLAP 数据集中的数据.之后,这些预测模型便可用于自动执行复杂的数据分析,以找出帮助识别新机会并选择有获胜把握的机会的趋势.
7)多维: OLAP (MOLAP): MOLAP 存储模式使得分区的聚合和其源数据的复本以多维结构存储在分析服务器计算机上.根据分区聚合的百分比和设计,MOLAP 存储模式为达到最快查询响应时间提供了潜在可能性.总而言之,MOLAP 更加适合于频繁使用的多维数据集中的分区和对快速查询响应的需要.
8)关系: OLAP (ROLAP): ROLAP 存储模式使得分区的聚合存储在关系数据库的表(在分区数据源中指定)中.但是,可为分区数据使用 ROLAP 存储模式,而不在关系数据库中创建聚合.
9)混合: OLAP (HOLAP): HOLAP 存储模式结合了 MOLAP 和 ROLAP 二者的特性.
10)粒度: 数据汇总的层次或深度.
11)聚合|聚集: 聚合是预先计算好的数据汇总,由于在问题提出之前已经准备了答案,聚合可以改进查询响应时间.
12)切块: 由多个维的多个成员限定的分区数据,称为一个切块.
13)切片: 由一个维的一个成员限定的分区数据,称为一个切片.
14)数据钻取: 最终用户从常规多维数据集、虚拟多维数据集或链接多维数据集中选择单个单元,并从该单元的源数据中检索结果集以获得更详细的信息,这个操作过程就是数据钻取.
备注: Mondrian 是基于ROLAP的
————————————————
数据立方体(Data Cube)
在介绍OLAP工具的具体使用前,先要了解这个概念:数据立方体(Data Cube)。
很多年前,当我们要手工从一堆数据中提取信息时,我们会分析一堆数据报告。通常这些数据报告采用二维表示,是行与列组成的二维表格。但在真实世界里我们分析数据的角度很可能有多个,数据立方体可以理解为就是维度扩展后的二维表格。
下图展示了一个三维数据立方体:
尽管这个例子是三维的,但更多时候数据立方体是N维的。它的实现有两种方式,本文后面部分会讲到。其中上一篇讲到的星形模式就是其中一种,该模式其实是一种连接关系表与数据立方体的桥梁。但对于大多数纯OLAP使用者来讲,数据分析的对象就是这个逻辑概念上的数据立方体,其具体实现不用深究。对于这些OLAP工具的使用者来讲,基本用法是首先配置好维表、事实表,然后在每次查询的时候告诉OLAP需要展示的维度和事实字段和操作类型即可。
下面介绍数据立方体中最常见的五大操作:切片,切块,旋转,上卷,下钻。
在数据立方体上的操作有:切片、切块、旋转、上卷和下钻。
数据立方体如图所示:
切片和切块(Slice and Dice)
在数据立方体的某一维度上选定一个维成员的操作叫切片,而对两个或多个维执行选择则叫做切块。
下图逻辑上展示了切片和切块操作:
这两种操作的 SQL 模拟语句如下,主要是对 WHERE 语句做工作。
# 切片
SELECT Locates.地区, Products.分类, SUM(数量)
FROM Sales, Dates, Products, Locates
WHERE Dates.季度 = 2
AND Sales.Date_key = Dates.Date_key
AND Sales.Locate_key = Locates.Locate_key
AND Sales.Product_key = Products.Product_key
GROUP BY Locates.地区, Products.分类
# 切块
SELECT Locates.地区, Products.分类, SUM(数量)
FROM Sales, Dates, Products, Locates
WHERE (Dates.季度 = 2 OR Dates.季度 = 3) AND (Locates.地区 = '江苏' OR Locates.地区 = '上海')
AND Sales.Date_key = Dates.Date_key
AND Sales.Locate_key = Locates.Locate_key
AND Sales.Product_key = Products.Product_key
GROUP BY Dates.季度, Locates.地区, Products.分类
旋转(Pivot)
旋转就是指改变报表或页面的展示方向。对于使用者来说,就是个视图操作,而从 SQL 模拟语句的角度来说,就是改变 SELECT 后面字段的顺序而已。下图逻辑上展示了旋转操作:
上卷和下钻(Rol-up and Drill-down)
上卷可以理解为”无视”某些维度;下钻则是指将某些维度进行细分。下图逻辑上展示了上卷和下钻操作:
这两种操作的 SQL 模拟语句如下,主要是对 GROUP BY 语句做工作。
# 上卷
SELECT Locates.地区, Products.分类, SUM(数量)
FROM Sales, Products, Locates
WHERE Sales.Locate_key = Locates.Locate_key
AND Sales.Product_key = Products.Product_key
GROUP BY Locates.地区, Products.分类
# 下钻
SELECT Locates.地区, Dates.季度, Products.分类, SUM(数量)
FROM Sales, Dates, Products, Locates
WHERE Sales.Date_key = Dates.Date_key
AND Sales.Locate_key = Locates.Locate_key
AND Sales.Product_key = Products.Product_key
GROUP BY Dates.季度.月份, Locates.地区, Products.分类
4. 其他OLAP操作
除了上述的几个基本操作,不同的OLAP工具也会提供自有的OLAP查询功能,如钻过,钻透等,本文不一一进行讲解。通常一个复杂的OLAP查询是多个这类OLAP操作叠加的结果。
OLAP的架构模式
1. MOLAP(Multidimensional Online Analytical Processing)
MOLAP架构会生成一个新的多维数据集,也可以说是构建了一个实际数据立方体。其架构如下图所示:
在该立方体中,每一格对应一个直接地址,且常用的查询已被预先计算好。因此每次的查询都是非常快速的,但是由于立方体的更新比较慢,所以是否使用这种架构得具体问题具体分析。
2. ROLAP(Relational Online Analytical Processing)
ROLAP架构并不会生成实际的多维数据集,而是使用星形模式以及多个关系表对数据立方体进行模拟。其架构如下图所示:
显然,这种架构下的查询没有MOLAP快速。因为ROLAP中,所有的查询都是被转换为SQL语句执行的。而这些SQL语句的执行会涉及到多个表之间的JOIN操作,没有MOLAP速度快。
3. HOLAP(Hybrid Online Analytical Processing)
这种架构综合参考MOLAP和ROLAP而采用一种混合解决方案,将某些需要特别提速的查询放到MOLAP引擎,其他查询则调用ROLAP引擎。
笔者发现一个有趣的现象,很多工具的发展都满足这个规律:工具A被创造,投入使用后发现缺点;然后工具B为了弥补这个缺点而被创造,但是带来了新的缺点;然后就会用工具C被创造,根据不同情况调用A和B。比较无语…
小结
整个数据仓库系统的开发会涉及到各种团队:数据建模团队,业务分析团队,系统架构团队,平台维护团队,前端开发团队等等。对于志在从事这方面工作的人来说,需要学习的还有很多。但对于和笔者一样志在成为一名优秀"数据科学家"的人来说,这些数据基础知识已经够用了。笔者看来,数据科学家的核心竞争优势在三个方面:数据基础,数据可视化,算法模型。这三个方面需要投入的时间成本递增,而知识的重要性递减。因此,数据库系列和数据仓库系列是性价比最高的两个系列哦。
作业要求:
创建表结构及插入模拟数据
此数据是从SQL Server2012版本数据库导出,仅供借鉴与参考
**1 销售分析表结构**
/****** Object: Table [dbo].[analysisTable] Script Date: 2019/3/11 15:33:52 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[analysisTable](
[timeID] [tinyint] NOT NULL,
[productID] [tinyint] NOT NULL,
[areaID] [tinyint] NOT NULL,
[number] [int] NOT NULL,
[money] [int] NOT NULL ) ON [PRIMARY] GO
地区维表表结构
CREATE TABLE [dbo].[areaTable](
[areaID] [tinyint] IDENTITY(1,1) NOT NULL,
[areaCou] [varchar](200) NOT NULL,
[areaPro] [varchar](50) NOT NULL,
[areaCity] [varchar](50) NOT NULL,
[areaDoor] [varchar](200) NOT NULL,
CONSTRAINT [PK_areaTable] PRIMARY KEY CLUSTERED
(
[areaID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
产品维表表结构
CREATE TABLE [dbo].[productTable](
[productID] [tinyint] IDENTITY(1,1) NOT NULL,
[productType] [nvarchar](50) NOT NULL,
[productName] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_productTable] PRIMARY KEY CLUSTERED
(
[productID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
时间维表表结构
CREATE TABLE [dbo].[timeTable](
[timeID] [tinyint] IDENTITY(1,1) NOT NULL,
[timeYear] [varchar](50) NOT NULL,
[timeMonth] [varchar](50) NOT NULL,
CONSTRAINT [PK_timeTable] PRIMARY KEY CLUSTERED
(
[timeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
多维数据操作
切片操作
操作SQL语句
select timeTable.timeMonth, productTable.productName, areaTable.areaDoor
from analysisTable, timeTable, productTable, areaTable
where
analysisTable.timeID = timeTable.timeID AND
analysisTable.productID = productTable.productID AND
analysisTable.areaID = areaTable.areaID AND
analysisTable.productID = 1;
在 Go 语言中,为便于存储及管理用户数据,其数据结构设计分为数组 Array、切片 Slice、映射 Map 三种结构。
近期又看了 Go 语言基础的内容,看了一下这三种结构实现的原理:
数组 Array
数组是切片和映射的基础数据结构;
数组是长度固定的数据类型并且在内存中也是连续分配的,固索引数组数据速度是非常快的;
声明数组时需要指定数组存储的类型及数量(数组的长度);
数组变量的类型包括数组长度和元素的类型,只有两部分都相同的数组才可相互赋值。
创建及初始化
一旦声明了数组,其本身的数据类型及长度都是不可以进行变更。
// 使用数组字面量声明数组
array := [5]int{1, 2, 3, 4, 5}
// 自动推导长度声明数组
array := […]int{1, 2, 3, 4, 5, 6}
// 使用 … 代替长度,根据初始化元素个数推导
// 声明数组并指定特定元素值
array := [5]int{1:10, 2:20}
指针类型
数组元素的类型可以为任何内置类型,也可以是某种结构类型,也可以是指针类型。
// 声明一个元素长度为 3 的指向字符串的指针数组
var array1 [3]*string
// 为指针数组指定元素
*array1[0] = “demo0”
*array1[1] = “demo1”
*array1[2] = “demo2”
多维数组
数组本身是一维数据,多维数组是由多个数组组合而来的。
// 声明一个二维数组
var array = [3][2]int
// 声明了一个两个维度为 3 和 2 的元素
// 初始化二维数组
var array = [3][2]int{ {1, 2}, {3, 4}, {5, 6}}
在函数间传递数组:由于在函数间传递变量时,传递的总是变量的值的副本,所以在传递数组变量时将拷贝整个数组!在定义函数时,对于较大的数据类型应该把参数设计为指针类型,这样在调用函数时,只需在栈上分配给每个指针8字节的内存,但这意味着会改变指针指向的值(共享的内存),其实大部分情况下应该使用切片类型,而不是数组。
切片 Slice
切片 slice 是引用类型,它引用了其指针字段所指向的底层数组的一部分或全部;
切片是围绕动态数组的概念构建的;
切片的动态增长是通过 append 来实现的;
缩小则是通过对它再次切片来实现,通过再次切片获得的新切片将和原切片共享底层数组,它们的指针指向同一个底层数组。
创建及初始化
切片类型有3个字段:
指针:指向切片所包含的第一个元素在底层数组中的地址;
长度:切片所包含的底层数组的元素的个数(切片可访问的元素的个数);
容量:切片允许增长到的最大元素个数,即底层数组的长度。
make 和切片字面量
// 使用 make 创建一个切片
slice := make([]int, 3)
// 创建一个具有长度和容量的切片
slice := make([]int, 1, 6)
// 长度为 1,容量为 6 个元素
nil 和空切片
// nil 字符串切片
var slice []string
// 空切片
slice := []int{}
// 空的整形切片
由于切片只是引用了底层数组,底层数组的数据并不属于切片本身,所以一个切片只需要 24字节的内存(在 64位机器上):指针字段 8字节、长度字段 8字节、容量字段 8字节。所以在函数之间直接传递切片是高效的,只需分配 24字节的栈内存。
len函数可返还切片的长度、cap函数可返还切片的容量。
映射 Map
映射 map 是用来存储一系列的无序键值对;
映射是无序的集合,其实现使用了散列表;
映射的散列表包含一组桶,每个桶里存储着一部分键值对;
映射内部使用了两个数组:
第一个数组:存储着用于选择桶的散列键的高八位值,该数组用于区分每个键值对要存在哪个桶里;
第二个数组:每个桶里都有一个字节数组,先依次存储了该桶里的所有键,之后存储了该桶的所有值;
创建及初始化
// 创建一个映射 存储学生信息
students := map[string]string{
“name” : “mengxiaoyu”,
“age” : “22”,
“sex” : “boy”,
“hobby”: “pingpang”,
}
// 显示映射所有信息
for key, value := range students{
fmt.printf(“key:%s, \t value:%s\n”, key, value);
}
遍历映射的键值对时的顺序是随机,若要有序的获得映射的键值对,则需要先遍历出映射的键存到一个切片中,然后排序该切片,最后遍历该切片,按切片中元素的顺序去映射中取对应的值。