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

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

问题引入

在日常的网站运维工作中,我们需要对网站客户端访问情况做统计、汇总、分析和报表展示,以数据来全面掌控网站运营和访问情况。当不可预知的意外情况发生时,我们可以快速发现问题以及采取相应的措施。比如:当网站受到黑客攻击时的流量陡增,又或者是网站某个资源发生意外抛异常等情况。
在提供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
......
AI 代码解读

其中:
%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
AI 代码解读

在建表过程中,我们设置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)
AI 代码解读

代码解释:由于列存储索引表增加了自增列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
AI 代码解读

单独执行该存储过程,返回的结果如下图所示:
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
AI 代码解读

执行该存储过程,返回如下的结果集:
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
AI 代码解读

执行该存储过程,返回如下结果集:
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
AI 代码解读

执行该存储过程,返回的结果集如下所示:
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
AI 代码解读

执行该存储过程,返回如下结果集:
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样例数据。

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
目录
打赏
0
0
0
0
9296
分享
相关文章
HTML5 Web 存储详解
HTML5 Web存储提供了两种客户端数据存储机制:**Local Storage**和**Session Storage**。Local Storage用于长期存储数据,即使关闭浏览器数据也依然存在,适用于保存用户偏好设置等信息。Session Storage则在标签或窗口关闭时清除数据,适合存储临时信息。两者均提供了简单的API进行数据的存取操作,但需要注意的是,Web存储并非加密存储,不应存放敏感信息。现代浏览器普遍支持Web存储,合理利用这两种存储方式可提升Web应用的用户体验。
如何解决 SQL Server 占用内存过多问题
SQL Server 占用过多内存会导致响应缓慢和查询性能低下。解决流程包括:1) 查看内存使用情况,2) 分析各数据库内存占用,3) 优化 SQL Server 配置(如限制最大内存),4) 优化查询(如创建索引),5) 持续监控效果。通过这些步骤可有效控制内存占用,提升系统性能。
120 0
Web学习_SQL注入_联合查询注入
联合查询注入是一种强大的SQL注入攻击方式,攻击者可以通过 `UNION`语句合并多个查询的结果,从而获取敏感信息。防御SQL注入需要多层次的措施,包括使用预处理语句和参数化查询、输入验证和过滤、最小权限原则、隐藏错误信息以及使用Web应用防火墙。通过这些措施,可以有效地提高Web应用程序的安全性,防止SQL注入攻击。
134 2
Web应用中的存储方式有哪些?
本文首发于微信公众号“前端徐徐”,介绍了几种常见的前端数据存储技术:Cookie、Web Storage(包括 localStorage 和 sessionStorage)、IndexedDB、Cache Storage 和 Memory Storage。每种技术的特点和使用场景不同,适用于不同的开发需求。文章详细解释了它们的使用方法、特点和应用场景,并提供了代码示例。
647 2
Web应用中的存储方式有哪些?
IDEA忽略node_modules减少内存消耗,提升索引速度
在后端开发中,IDEA 在运行前端代码时,频繁扫描 `node_modules` 文件夹会导致高内存消耗和慢索引速度,甚至可能会导致软件卡死。为了改善这一问题,可以按照以下步骤将 `node_modules` 文件夹设为忽略:通过状态菜单右键排除该文件夹、在设置选项中将其加入忽略列表,并且手动修改项目的 `.iml` 文件以添加排除配置。这些操作可以有效提高IDE的运行性能、减少内存占用并简化项目结构,但需要注意的是,排除后将无法对该文件夹进行索引,操作文件时需谨慎。
427 4
IDEA忽略node_modules减少内存消耗,提升索引速度
|
6月前
|
SQL
Web for Pentester SQL sql注入靶场
Web for Pentester SQL sql注入靶场
HTML5 Web 存储详解
HTML5 Web 存储包括 `localStorage` 和 `sessionStorage`,前者提供持久存储且无过期时间,后者仅在会话期间有效。两者均支持键值对形式存储数据,容量约为 5-10 MB。`localStorage` 适用于用户偏好设置、登录状态保持及离线应用缓存;`sessionStorage` 则用于临时数据如表单输入。数据以字符串形式存储,可通过 `JSON` 方法处理对象。由于数据存储于本地,不适合存放敏感信息。示例代码展示了如何使用按钮将输入框内容保存至 `localStorage` 并进行清除操作。
惊!Python Web安全黑洞大曝光:SQL注入、XSS、CSRF,你中招了吗?
在数字化时代,Web应用的安全性至关重要。许多Python开发者在追求功能时,常忽视SQL注入、XSS和CSRF等安全威胁。本文将深入剖析这些风险并提供最佳实践:使用参数化查询预防SQL注入;通过HTML转义阻止XSS攻击;在表单中加入CSRF令牌增强安全性。遵循这些方法,可有效提升Web应用的安全防护水平,保护用户数据与隐私。安全需持续关注与改进,每个细节都至关重要。
184 5
深度揭秘:Python Web安全攻防战,SQL注入、XSS、CSRF一网打尽!
在Web开发领域,Python虽强大灵活,却也面临着SQL注入、XSS与CSRF等安全威胁。本文将剖析这些常见攻击手段,并提供示例代码,展示如何利用参数化查询、HTML转义及CSRF令牌等技术构建坚固防线,确保Python Web应用的安全性。安全之路永无止境,唯有不断改进方能应对挑战。
139 5
前端开发中,Web Storage的存储数据的方法localstorage和sessionStorage的使用及区别
前端开发中,Web Storage的存储数据的方法localstorage和sessionStorage的使用及区别
239 0

热门文章

最新文章