慕ke 大数据工程师2023
核心代码,注释必读
// download:
3w ukoou com
大数据技术是指对大规模数据的收集、分析、挖掘和应用的技术。数据的采集是大数据技术的第一步,是指通过某种方法或手段收集各种产生数据。举个例子,比如说现在的互联网网站都有日志记录的功能,把用户在网站上的所有的行为,包括浏览点击购买等等,都记录下来。这样后台服务就能够分析用户的兴趣爱好并为其推荐个性化的产品。再比如说气象部门会在城市的各个角落布置各种传感器,来采集气象数据。物流公司一般会跟踪采集物流数据,实时掌握物流信息。超市会在后台的服务器上记录顾客的购买数据。总的来说,所有可能有价值的数据都会被采集,被数字化。
数据的采集和记录只是第一步,并不是我们的最终目的。我们的目的是分析数据的规律,挖掘数据的潜在价值,为决策提供依据,或者直接用到相应的产品或服务中。个人认为这就是大数据技术的核心。通过对数据的挖掘我们可以知道啤酒和尿布这两件商品是可以捆绑在一起销售的,我们还可以知道某个具体的用户可能偏好什么样的商品,某个广告被点击的概率有多大,用户在一个具体的场景下会有什么需求,一次贷款的风险有多高。我们甚至能够发现用户为了使得自己的商品在搜索结果中排名靠前使用了哪些作弊手段。这些是数据挖掘和机器学习等技术的应用,也是发掘数据价值的关键手段。只有挖掘出数据的价值,数据的存在才变得有意义。数据挖掘工程师是大数据时代最紧缺的人才。数据价值体现在于对其进行的应用。比如说各种可视化的报表,为企业高层的决策提供依据。用户和商品数据可以用来为用户提供个性化的推荐服务,缩短用户的查找路径,为用户提供有效的信息。
大数据操作:删除和去重
一,从海量数据中删除数据
从海量数据表中删除一半数据,看似简单,使用delete命令,如果真这么干,SQL Server产生的事务日志暴增,估计会把服务器硬盘爆掉。数据库的恢复模式会影响日志文件的增长,在删除海量数据时,根据采用的方法,相应地把恢复模式设置为simple,或bulk_logged 模式,能够在很大程度上减少删除操作产生的事务日志,从而避免日志暴增。
另外,慕课网大数据在删除数据时,把表上的多余索引删除(注意,是删除多余的索引),只保留一个必需的索引;在数据删除完成之后,再重建索引,能够提高数据删除操作的性能。有人做过实验,从存储1.6亿条记录的大表中删除数据,每删除400万条要消耗1.5 - 3小时,越到后面速度越慢,为什么?这是因为,每次删除数据时,数据库都要相应地更新索引,这是很慢的硬盘 IO操作,并且,越到后面,索引碎片越多,更新索引就越慢,这就是在删除400万条记录时,一开始只消耗1.5小时,后面要消耗3小时原因。
最后,根据保留数据占总数据量的比例,选择不同的方法删除数据。如果大表中保留的数据较少,可以先把保留的数据存储到临时表中,然后,把原始表删除,这样能够利用大容量日志操作,来减少日志的增长和提高数据插入的速度。
1,循环删除,避免日志文件暴增
在从海量数据表中删除大量数据时,为了避免日志文件暴增,通常采用循环删除方法:首先设置恢复模式为simple,然后每次删除操作都只删除部分数据,这样,当单个删除操作执行完成时,事务日志会被及时清理,事务日志一般保持单个删除操作的事务日志量。
循环删除的伪代码如下,该方法仍有一些局限性,耗时过长,并且会长期使数据库处于简单恢复模式下:
复制代码 --ALTER DATABASE database_name SET RECOVERY SIMPLE ;
while @index<@EndIndex begin delete table_name where index<=@index;
set @index+=@Increment
end 复制代码 2,将数据插入到临时表中,把原表drop
如果原始表有一半以上的数据要被删除,从原始表中执行delete命令删除数据,效率十分低下,可以考虑,把原始表中的数据通过select语句筛选出来,然后批量插入导新表中,这种方式利用了大容量日志(Bulk Logged)操作的优势。由于 SELECT INTO,INSERT SELECT 是大容量日志操作,select命令不会产生大量日志文件,因此,执行插入比执行删除的效率更高。最后,执行drop命令,删除整个原始表,几乎不消耗任何时间。
复制代码 --ALTER DATABASE database_name SET RECOVERY BULK_LOGGED ;
insert into new_table select column_list from original_table where filter_retain
drop table original_table 复制代码 把临时表重命名,执行 sp_rename 或手动重命名,其中 @objtype 参数是可选的,默认值是NULL,对表重命名,设置参数 @objtype='object':
sp_rename [ @objname = ] 'object_name' , [ @newname = ] 'new_name'
[ , [ @objtype = ] 'object_type' ]
3,对分区表执行分区转移操作
SQL Server的分区表实际上是一系列物理上独立存储的“表”(也叫做分区)构成的,如果要删除的数据位于同一个分区,或者,一个分区中的数据都需要被删除,那么可以把该分区转移(switch)到一个临时表中,由于分区的转移仅仅是元数据库的变更,因此,不会产生任何的数据IO,分区转移瞬间完成。被剥离的分区,通过drop命令删除,整个过程仅仅会产生少量的IO操作,用于元数据变更;而不会产生用于数据删除的IO操作,这种方法,耗时最短,资源消耗最小,效率最高。
alter table original_table SWITCH PARTITION source_partition_number TO temporary_table
drop table temporary_table 二,从海量数据中去重
数据去重,分为部分列去重和全部列去重,全部列去重,使用distinct子句来实现,由于distinct操作符会创建在tempdb中临时表,因此,distinct操作是IO密集型的操作。而部分列去重,一般采用row_number排名函数来实现,也可以考虑使用忽略重复值的唯一索引来实现。在实际的项目开发中,部分列去重更为常见。
1,使用row_number函数来实现
选择排名函数,是因为排名函数有部分列分区排序的功能:首先在部分列上创建索引,这样数据库引擎能够根据索引列快速排序,然后通过row_number函数和cte来实现重复数据的删除。在数据去重时,需要注意,如果删除的数据量太大,数据库引擎会产生大量的事务日志,导致日志文件暴增,在选择该方法时,需要慎重。
复制代码 create index index_name on table_name ( index_columns ) with(data_compression=page);
with cte as ( select index_columns, row_number() over(partition by index_columns order by ...) as rn from table_name ) delete from cte where rn>1 复制代码 2,使用忽略重复值的唯一索引来实现
通过插入和忽略重复值实现部分列的去重,相对来说,更容易控制,用户可以通过循环插入方式来执行,这样,在单独的一个事务中,控制插入数据的数量,能够控制产生的事务日志不至于太大,对于海量数据的去重,建议采用该方法。
创建一个临时表,在部分列上创建忽略重复值的唯一索引:
复制代码 create unique index index_name on new_table ( index_columns ) with(ignore_dup_key=on) 复制代码 由于SQL Server不允许在包含重复值的数据表上创建唯一索引,因此,必须创建一个新的空表,新表时原始表的结构的复制,在部分列上创建忽略重复值的唯一索引。在执行插入操作时, IGNORE_DUP_KEY 选项会忽略重复的索引键值,并抛出警告(Warning)