MSSQL · 应用案例 · 基于内存优化表的列存储索引分析Web Access Log

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS SQL Server,基础系列 2核4GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介: 问题引入在日常的网站运维工作中,我们需要对网站客户端访问情况做统计、汇总、分析和报表展示,以数据来全面掌控网站运营和访问情况。当不可预知的意外情况发生时,我们可以快速发现问题以及采取相应的措施。比如:当网站受到黑客攻击时的流量陡增,又或者是网站某个资源发生意外抛异常等情况。在提供Web服务的服务器上,比如IIS、Apache都存在访问日志记录,这篇是文章是以SQL Server 2016基于内

问题引入

在日常的网站运维工作中,我们需要对网站客户端访问情况做统计、汇总、分析和报表展示,以数据来全面掌控网站运营和访问情况。当不可预知的意外情况发生时,我们可以快速发现问题以及采取相应的措施。比如:当网站受到黑客攻击时的流量陡增,又或者是网站某个资源发生意外抛异常等情况。
在提供Web服务的服务器上,比如IIS、Apache都存在访问日志记录,这篇是文章是以SQL Server 2016基于内存优化表的列存储索引来分析Apache Web Access Log为例,讲解分析网站访问情况,因此,我们需要解决以下几个问题:

  • Apache Web Access Log格式介绍

  • 列存储索引表结构的设计

  • Apache Web Access Log导入到列存储索引表

  • 网站访问流量统计

  • 客户端主机访问的分布情况

  • 客户端主机访问的资源统计

  • 异常URI访问统计

  • Response Code分布情况

日志格式介绍

在设计基于内存优化表的列存储索引表结构之前,我们首先必须要对Apache Web Access Log服务器普通日志格式了解得非常清楚,以日志结构来建立我们SQL Server 2016的列存储索引表结构,在此,仅以一条日志记录格式来分析:

## 通用日志格式
LogFormat "%h %l %u %t \"%r\" %>s %b" common

## 其中一条日志举例
64.242.88.10 - - [07/Mar/2004:16:47:12 -0800] "GET /robots.txt HTTP/1.1" 200 68
......

其中:

  • %h:发送请求到服务器的客户端主机(IP或者是主机名),本例中的64.242.88.10;

  • %l:确定访问用户的标识(因为不可靠,通常不会使用,用中划线来填充),本例中的第一个中划线;

  • %u:由HTTP认证确定的用户名称,本例中的第二个中划线;

  • %t:服务器端收到客户端请求的时间点,格式为:[day/month/year:hour:minute:second zone],本例中的[07/Mar/2004:16:47:12 -0800];

  • %r:置于双引号之间的请求详细信息,包括三部分:请求方法、请求的资源和客户端协议及版本。本例中的”GET /robots.txt HTTP/1.1”;

  • %>s:返回的Response Code,比如本例中200表示访问成功;

  • %b:返回给客户端的对象大小,不包含HTTP Header,单位为byte,本例中获取了68 byte资源。

基于内存优化表的列存储索引表结构设计

基于以上对Apache Web Access Log格式的分析,我们可以建立格式对等的基于内存优化表的列存储索引表。这种类型的表数据会按列压缩存放在内存中,可以大大减少OLAP查询对IOPS的消耗,提高OLAP分析查询的性能。其表结构如下所示:

USE CCSI2016
GO
DROP TABLE IF EXISTS dbo.WebAccessLOG
GO

CREATE TABLE dbo.WebAccessLOG (
[LogId] BIGINT IDENTITY(1,1) NOT NULL,
[RemoteHost] [varchar](100) NULL,
[UserIdentity] varchar(10) NULL,
[UserName] varchar(10) NULL,
[RequestTime] varchar(50) NULL,
[Timezone] varchar(10) NULL,
[Action] varchar(10) NULL,
[URI] VARCHAR(1000) NULL,
[Version] VARCHAR(20) NULL,
[StatusCode] varchar(5) NULL,
[Size_Byte] INT NULL,
[Indate] DATETIME NOT NULL CONSTRAINT DF_Indate DEFAULT(GETDATE()),
CONSTRAINT PK_WebAccessLOG PRIMARY KEY NONCLUSTERED HASH ([LogId]) WITH (BUCKET_COUNT = 10000000)
)WITH(MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA) ;
GO

ALTER TABLE dbo.WebAccessLOG
	ADD INDEX CCSI_WebAccessLOG CLUSTERED COLUMNSTORE
;
GO

在建表过程中,我们设置MEMORY_OPTIMIZED = ON,表示该表为内存优化表,此类表数据会存放在内存中;DURABILITY = SCHEMA_AND_DATA表示,我们需要持久化表结构和数据到磁盘上,以防止服务意外终止而导致的数据丢失;最后一句ALTER TABLE ADD INDEX CLUSTERED COLUMNSTORE表示为该内存优化表建立聚集列存储索引,此类型表数据会被压缩存放在内存中。

导入日志信息到列存储索引表

我们完成了基于内存优化表的列存储索引表设计以后,接下来,我们需要将Apache Web Access Log文件导入到该表中。由于Log文件不带表头,第一行就直接是数据;每行之间的信息以空格分割;行与行之间以换行分割,所以,我们可以使用BULK INSERT的方式将Log文件导入列存储索引表。方法如下:

USE CCSI2016
GO
-- Create view base on log table
DROP VIEW IF EXISTS dbo.[UV_WebAccessLOG]
GO
CREATE VIEW [dbo].[UV_WebAccessLOG]
AS
SELECT [RemoteHost]
	,[UserIdentity]
	,[UserName]
	,[RequestTime]
	,[Timezone]
	,[Action]
	,[URI]
	,[Version]
	,[StatusCode]
	,[Size_Byte]
FROM CCSI2016.dbo.WebAccessLOG WITH(NOLOCK)
GO

-- BULK INSERT Log into view
BULK INSERT dbo.[UV_WebAccessLOG]
FROM 'C:\Temp\access_log'
WITH (
 FIRSTROW = 1,
 FIELDTERMINATOR = ' ',
 ROWTERMINATOR = '\n'
)

-- Init data
;WITH DATA
AS(
	SELECT TOP (1545) LogId
	FROM CCSI2016.dbo.WebAccessLOG AS A
	ORDER BY Indate DESC
)
UPDATE TOP(1545) A
SET RequestTime = REPLACE(RequestTime, '[', '')
FROM CCSI2016.dbo.WebAccessLOG AS A
WHERE LogId IN(SELECT LogId FROM DATA)

代码解释:由于列存储索引表增加了自增列LogId和时间字段Indate,我们无法直接将数据BULK INSERT到正式表,需要建立视图dbo.[UV_WebAccessLOG]来作为中间桥梁;数据导入完毕后,由于RequestTime字段含有中括号左半部分,我们需要将中括号刷洗掉。至此,列存储索引表创建完毕,访问Log日志也已经导入,接下来就是详细的统计分析了。

网站流量统计分析

网站的流量统计是以时间为单位统计所有客户端访问网站的点击数量和以此获取到的资源总流量大小。时间单位可以小到每秒,大到每小时或者每天为单位来统计,这个统计值可以数据化网站的访问流量,随时监控网站是否有意外发生,或者是意外的突发访问,比如:被黑客攻击导致流量突然增大。在此,仅以天为时间单位,描述网站流量统计分析的方法。

USE CCSI2016
GO
DROP PROCEDURE IF EXISTS dbo.UP_LoadingAnalysis
GO
CREATE PROCEDURE dbo.UP_LoadingAnalysis 
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER 
AS BEGIN ATOMIC 
WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english')
	SELECT
		Day = CONVERT(CHAR(10), RequestTime, 120) 
		, minSize = CAST(MIN(Size_Byte) / 1024. AS DECIMAL(8, 2))
		, maxSize = CAST(MAX(Size_Byte) / 1024. AS DECIMAL(8, 2))
		, avgSize = CAST(AVG(Size_Byte) / 1024. AS DECIMAL(8, 2))
		, sumSize = CAST(SUM(Size_Byte) / 1024. AS DECIMAL(8, 2))
		, NoOfHits = COUNT(1)
	FROM dbo.WebAccessLOG
	GROUP BY CONVERT(CHAR(10), RequestTime, 120)
	ORDER BY 1 ASC
END
GO

单独执行该存储过程,返回的结果如下图所示:

01.png

将返回的结果,做成一个Chart图表,如下图所示:

02.png

从返回的数据结果集和做出的图表展示,我们很容易发现2004年3月8号这一天无论是点击率还是网站流量都是6天内最高的。那么,对这些流量贡献排名前十的是哪些客户端机器呢?请看下一小节。

客户端主机访问分布情况

流量统计部分只能回答“哪个时间段流量超标”的问题,如果我们需要知道流量超标时间段内,到底是哪个或者哪些客户端主机访问量过大,客户端主机访问流量分布情况如何?在此,我们以2004年3月8号为例,分析客户端主机访问分布情况,代码如下所示:

USE CCSI2016
GO
DROP PROCEDURE IF EXISTS dbo.UP_FrequentAccessHosts
GO
CREATE PROCEDURE dbo.UP_FrequentAccessHosts 
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER 
AS BEGIN ATOMIC 
WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english')

	SELECT RemoteHost
		, NoOfAccess = COUNT(1)
		, Size = cast(SUM(Size_Byte)/ 1024. as decimal(8,2))
	FROM dbo.WebAccessLOG
	WHERE [RequestTime] >= '08/Mar/2004' 
		AND [RequestTime] <= '09/Mar/2004'
	GROUP BY RemoteHost
	HAVING COUNT(1) >= 10
	ORDER BY RemoteHost ASC
	
END 
GO

执行该存储过程,返回如下的结果集:

03.png

将这个返回的结果集,做成图表展示如下图所示:

04.png

从返回的结果集和图表展示,我们很容易得出,来自客户端机器64.242.88.10的点击率和访问流量远远高于其他的客户端。至此,我们已经成功的找到了访问量最大的客户端机器IP地址。我们可以针对这个客户端主机进行分析,看看是否存在黑客攻击行为,如果存在,可以考虑从网络层禁止这个IP访问网站资源。那么,客户端主机访问的是哪些网站资源呢?请继续查看下一节。

客户端主机访问的资源

根据客户端主机访问分布情况部分,我们已经找到访问量最大的某个或者某几个客户端主机,接下来我们需要回答“客户端主机访问的Web资源是哪些?经常被频繁访问的资源集中在哪些URI上?”。如果能够找出这两个问题,我们可以考量将对应的资源放到缓存设备中,以此来增加缓存的命中率,提高客户机访问网站资源的速度。方法如下:

USE CCSI2016
GO
DROP PROCEDURE IF EXISTS dbo.UP_FrequentAccessResouceURI
GO
CREATE PROCEDURE dbo.UP_FrequentAccessResouceURI 
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER 
AS BEGIN ATOMIC 
WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english')
	-- TOP 10 URI
	SELECT TOP 10
			URI
			, NoOfHits = COUNT(1)
			, Size = CAST(SUM(Size_Byte)/ 1024. as decimal(8,2))
	FROM dbo.WebAccessLOG
	GROUP BY URI
	ORDER BY 2 DESC
END
GO

执行该存储过程,返回如下结果集:

05.png

依据该结果集,做成图表,展示如下图所示:

06.png

从结果集和图表展示的统计结果来看,点击率最高的是获取/twiki/pub/TWiki/TWikiLogos/twikiRobot46x50.gif资源的时候,而流量最大集中在对资源/twiki/bin/view/Main/WebHome的访问上。

Response Code分布情况

在另一个方面,网站客户端主机访问成功率是衡量一个网站是否正常工作很重要的指标,我们可以统计客户端访问HTTP服务的Response Code分布情况,来获取客户端主机访问成功率,以此来判断HTTP服务工作情况是否良好。方法如下:

USE CCSI2016
GO
DROP PROCEDURE IF EXISTS dbo.UP_ResponseCodeAnalysis
GO
CREATE PROCEDURE dbo.UP_ResponseCodeAnalysis 
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER 
AS BEGIN ATOMIC 
WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english')
	SELECT
		 StatusCode
		, ResponseCodeCount = COUNT(1)
	FROM dbo.WebAccessLOG
	GROUP BY StatusCode
	ORDER BY 1 ASC
END
GO

执行该存储过程,返回的结果集如下所示:

07.png

将该存储过程返回的结果集,做成图表如下所示:

08.png

从存储过程执行的结果集和展示的图表来看,资源访问成功率(返回为200的概率)仅为82.46%,换句话说,100个客户端访问中,仅有82.46个是成功访问,成功率过低,还有很大的提升空间。因此,我们需要深入调查到底是访问哪些URI导致了错误发生?请看下一小节。

报错排名前十的URI

有时候,访问我们的Web服务资源的时候,会发生很多意外情况(返回值不是200),我们需要对这些错误的发生有全面的掌控,比如:统计Web站点上发生错误次数排名前十的资源有哪些?分析出这个问题的答案以后,我们就可针对错误的资源,定向查找访问失败的原因。

USE CCSI2016
GO
DROP PROCEDURE IF EXISTS dbo.UP_FrequentExceptionURI
GO
CREATE PROCEDURE dbo.UP_FrequentExceptionURI
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER 
AS BEGIN ATOMIC 
WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english')
	SELECT TOP 10
			URI
			, NoOfHits = COUNT(1)
			, Size = CAST(SUM(Size_Byte)/ 1024. as decimal(8,2))
	FROM dbo.WebAccessLOG
	WHERE StatusCode <> 200
	GROUP BY URI
	ORDER BY 2 DESC
END
GO

执行该存储过程,返回如下结果集:

09.png

将该结果集,做成图表,展示如下所示:

10.png

从存储过程返回的结果集和图表展示的统计结果来看,资源/twiki/pub/TWiki/TWikiLogos/twikiRobot46x50.gif点击发生的错误最多,而资源/twiki/bin/edit/Main/PostConf?topicparent=Main.PostfixCommands发生的错误流量最大。所以最终,我们找到了经常报错的一些URI资源,我们需要解决这些错误,最终达到提高客户端访问成功率的目的。

最后总结

本篇月报是SQL Server列存储索引系列月报的最后一篇,介绍SQL Server 2016基于内存优化表的列存储索引的应用案例,分析Apache Web Access Log,以此来帮助我们分析和掌控网站的运行情况。至此,我们总共分析了四篇关于SQL Server列存储技术,跨度从SQL Server 2012到SQL Server 2014,最终到SQL Server 2016。

SQL Server · 特性分析 · 2012列存储索引技术:介绍SQL Server 2012列存储索引技术。

SQL Server · 特性介绍 · 聚集列存储索引:介绍SQL Server 2014中的聚集列存储索引技术。

MSSQL · 特性分析 · 列存储技术做实时分析:介绍了SQL Server 2016列存储索引技术在实时分析场景中应用。

参考文档

Log Files:Apache Web Access Log的日志格式介绍。

Import and analyze IIS Log files using SQL Server:基于内存优化表的列存储索引表结构设计。

Apache (Unix) Log Samples:本篇文章分析的Apache Web Access Log样例数据。

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
3月前
|
存储 弹性计算 缓存
阿里云服务器ECS经济型、通用算力、计算型、通用和内存型选购指南及使用场景分析
本文详细解析阿里云ECS服务器的经济型、通用算力型、计算型、通用型和内存型实例的区别及适用场景,涵盖性能特点、配置比例与实际应用,助你根据业务需求精准选型,提升资源利用率并降低成本。
255 3
|
2月前
|
存储
阿里云轻量应用服务器收费标准价格表:200Mbps带宽、CPU内存及存储配置详解
阿里云香港轻量应用服务器,200Mbps带宽,免备案,支持多IP及国际线路,月租25元起,年付享8.5折优惠,适用于网站、应用等多种场景。
657 0
|
4月前
|
Java 数据库 网络架构
菜鸟之路Day36一一Web开发综合案例(部门管理)
本文详细记录了基于Spring Boot的Web开发综合案例——部门管理功能的实现过程。从环境搭建到功能开发,涵盖数据库表设计、Spring Boot项目创建、依赖引入、配置文件设置以及Mapper、Service、Controller的基础结构构建。文章重点讲解了查询、删除、新增和修改部门信息的业务逻辑实现,遵循RESTful规范设计接口,并通过统一响应结果类`Result`优化前后端交互体验。借助Spring的IoC容器管理与MyBatis的SQL映射,实现了高效的数据操作与业务处理,最终完成部门管理的全功能开发。
122 12
|
2月前
|
存储 人工智能 自然语言处理
AI代理内存消耗过大?9种优化策略对比分析
在AI代理系统中,多代理协作虽能提升整体准确性,但真正决定性能的关键因素之一是**内存管理**。随着对话深度和长度的增加,内存消耗呈指数级增长,主要源于历史上下文、工具调用记录、数据库查询结果等组件的持续积累。本文深入探讨了从基础到高级的九种内存优化技术,涵盖顺序存储、滑动窗口、摘要型内存、基于检索的系统、内存增强变换器、分层优化、图形化记忆网络、压缩整合策略以及类操作系统内存管理。通过统一框架下的代码实现与性能评估,分析了每种技术的适用场景与局限性,为构建高效、可扩展的AI代理系统提供了系统性的优化路径和技术参考。
146 4
AI代理内存消耗过大?9种优化策略对比分析
|
2月前
|
存储 缓存 NoSQL
内存管理基础:数据结构的存储方式
数据结构在内存中的存储方式主要包括连续存储、链式存储、索引存储和散列存储。连续存储如数组,数据元素按顺序连续存放,访问速度快但扩展性差;链式存储如链表,通过指针连接分散的节点,便于插入删除但访问效率低;索引存储通过索引表提高查找效率,常用于数据库系统;散列存储如哈希表,通过哈希函数实现快速存取,但需处理冲突。不同场景下应根据访问模式、数据规模和操作频率选择合适的存储结构,甚至结合多种方式以达到最优性能。掌握这些存储机制是构建高效程序和理解高级数据结构的基础。
204 2
|
2月前
|
存储 弹性计算 固态存储
阿里云服务器配置费用整理,支持一万人CPU内存、公网带宽和存储IO性能全解析
要支撑1万人在线流量,需选择阿里云企业级ECS服务器,如通用型g系列、高主频型hf系列或通用算力型u1实例,配置如16核64G及以上,搭配高带宽与SSD/ESSD云盘,费用约数千元每月。
191 0
|
3月前
|
XML SQL 前端开发
菜鸟之路Day37一一Web开发综合案例(员工管理)
本文介绍了基于Web开发的员工管理综合案例,涵盖分页查询、条件分页查询、删除员工和新增员工四大功能模块。通过前后端交互,前端传递参数(如页码、每页记录数、查询条件等),后端使用MyBatis与PageHelper插件处理数据查询与操作。代码结构清晰,包括Controller层接收请求、Service层业务逻辑处理以及Mapper层数据访问,并结合XML动态SQL实现灵活的条件查询。此外,新增与删除功能分别通过POST与DELETE请求完成,确保系统功能完整且高效。
124 7
|
3月前
|
存储 前端开发 Java
菜鸟之路Day38一一Web开发综合案例(三)
本文介绍了Web开发中的文件上传与员工信息修改的综合案例,涵盖前端到后端的完整流程。重点讲解了阿里云OSS的集成,包括Bucket创建、密钥获取及SDK使用,并通过Spring Boot实现文件上传功能。同时,详细描述了员工信息查询与修改的操作逻辑,涉及Controller、Service和Mapper层代码实现。最后探讨了配置文件的优化,对比@Value与@ConfigurationProperties注解,展示了如何通过实体类批量注入配置参数,提升代码可维护性与灵活性。
95 1
|
3月前
|
监控 安全 Linux
AWK在网络安全中的高效应用:从日志分析到威胁狩猎
本文深入探讨AWK在网络安全中的高效应用,涵盖日志分析、威胁狩猎及应急响应等场景。通过实战技巧,助力安全工程师将日志分析效率提升3倍以上,构建轻量级监控方案。文章详解AWK核心语法与网络安全专用技巧,如时间范围分析、多条件过滤和数据脱敏,并提供性能优化与工具集成方案。掌握AWK,让安全工作事半功倍!
85 0