前言  

  一般来说,物理表的增、删、改、查都受到数据量的制约,进而影响了性能。

  很多情况下,你所负责的业务关键表中,每日变动的数据库与不变动的数据量比较,相差非常大。

  这里我们将变动的数据称为动态数据,不变动的数据称为静态数据。

  举个例子,1张1000W的表,每日动态数据只有1W条,999W条的数据都为静态。往往select或者重复改变的数据都在动态数据中。比如订单表。

  所以,如果将动态数据库从表中剥离出来,分割两张表,一张动态数据表,一张静态数据表,从数据量的角度来看,性能是不是就会自然提高了?

  下图为一张现实表和一张理想化的结构   (蓝色为静态数据:1000W、黄色为动态数据:100W):

  

  希望动态数据和静态数据分割开

  

  

  想法再好,也比不上现实的残酷。很多朋友可能都想到这种架构,但实现起来问题非常多:

  

  1.  如何将动态数据自动从静态数据中剥离?如何维护?

  2.  程序代码改动量不可预计。尤其核心表的使用遍布各地,分割成两张表后,所有代码基本都要重构。

  3.  表分区是否可以达到同样目的,NO~因为表分区无法100%区分动态与静态,而且分区列的使用决定了效率。

  下面开始,进入本次主题,如何在SQL Server中达到动态数据、静态数据分割;两表数据如何自动维护;程序统一访问逻辑表名,零维护成本。

正文

  实现方法:利用视图 + 视图触发器

  没错,没有了~就是靠这两货,就解决了,下面我们来看看逻辑图(画的不好,见谅)。

  

最后,让我们来看看具体事例

1.  创建demo数据库,和动态表(TB_A_NEW)、历史表(TB_A_OLD)

CREATE DATABASE demo
GO
ALTER DATABASE demo ADD FILEGROUP HekatonFG CONTAINS MEMORY_OPTIMIZED_DATA;
GO
ALTER DATABASE demo ADD FILE( NAME = 'Memory', FILENAME ='C:\Memory.ndf') TO FILEGROUP [HekatonFG];
GO
CREATE TABLE TB_A_OLD
(
id INT IDENTITY(1,1) PRIMARY KEY,
     NAME NVARCHAR(36)
GO
CREATE TABLE TB_A_NEW
(
id INT IDENTITY(1, 1) PRIMARY KEY,
NAME NVARCHAR(36)
)
GO
INSERT INTO TB_A_OLD
SELECT Newid()
GO 10

这个时候的两张表的数据如下:

然后,我们为了保证动态表的新增数据的自增值是静态表的当前标识值+1,这样两表记录合并才能衔接。

DECLARE @IDENT BIGINT

SELECT @IDENT = Ident_current('TB_A_OLD') + 1

DBCC checkident('TB_A_NEW', reseed, @IDENT)

  

创建视图(View_TB_A)

CREATE VIEW [dbo].[View_TB_A]
AS
SELECT *
FROM TB_A_NEW
UNION ALL
SELECT old.*
FROM TB_A_OLD old
LEFT JOIN TB_A_NEW new
ON old.id = new.id
WHERE new.NAME IS NULL GO

创建视图触发器(Insert、Update)

USE demo

GO

CREATE TRIGGER [dbo].[TR_Insert]
ON [dbo].[View_TB_A]
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON INSERT INTO TB_A_NEW
(NAME)
SELECT NAME
FROM inserted
END GO USE demo GO CREATE TRIGGER [dbo].[TR_Update]
ON [dbo].[View_TB_A]
INSTEAD OF UPDATE
AS
BEGIN
SET NOCOUNT ON --1. 判断update中,包含的记录是否都在new表中
DECLARE @count BIGINT SELECT @count = Count(1)
FROM deleted UPDATE TB_A_NEW
SET NAME = b.NAME
FROM TB_A_NEW a,
inserted b
WHERE a.id = b.id IF @@ROWCOUNT < @count
BEGIN
SET IDENTITY_INSERT TB_A_NEW ON INSERT INTO TB_A_NEW
(id,
NAME)
SELECT i.id,
i.NAME
FROM inserted i
LEFT JOIN TB_A_NEW n
ON i.id = n.id
WHERE n.NAME IS NULL
END
END GO

下面,我们来测试下SELECT、UPDATE、INSERT

Select

SELECT的结果就是刚才的插入10条记录,通过!

Insert

INSERT到视图中,会在TB_A_NEW表中新增一条记录,TB_A_OLD并没有任何变化。也就是自动分配到了动态表中,通过!

Update

然后我们继续更新id=2的记录,看看结果如何

最后,我们继续查询视图VIEW_TB_A,看看最终返回的结果。

看到最终结果11条,并且之前通过视图的更新,插入都返回了正确结果,通过!

至此,测试结束,通过视图和视图触发器,实现了统一名称访问,底册物理表分割动态表和静态表,测试过程并不包含delete,感兴趣的童鞋稍微琢磨下就出来了。

如果需要合并动态表与静态表,只需将id相同记录,更新到静态表,静态表不存在的id对应动态数据,插入到静态表中即可。

本次内容主意在实现方法,具体性能提升测试,日后再做说明,简单说下,就是触发器的逻辑处理,放在了物理表插入数据之前。将数据分类存储。所以逻辑处理开销会增加,但是物理存储分割。在数据量影响性能明显的场景中会非常适用。

如果你的数据库是SQL Server 2014,那么将静态和动态表定义到内存表中,动态数据又剥离了,具体提升多少这里不做猜测,有环境的朋友可以试试哦~

另:

  利用以上方法,也可以解决肖桑(大菠萝)和笑东风提到的的主键int修改为bigint型问题

  (http://www.cnblogs.com/TeyGao/p/4463389.html)

      如果每日一次合并动态表与静态表数据,动态数据表就是当日的差异数据哦,扩展使用非常方便。

好~就到这里,再见吧~

【Paddy】如何将物理表分割成动态数据表与静态数据表的更多相关文章

  1. [转]在Sql Server中将字符串分割成表格数据示例

    本文转自:http://www.lmwlove.com/ac/ID718 比如我们有一个字符串 ) select @appName ='UserID=admin,Account=ABC' 然后我们要以 ...

  2. 随笔 JS 字符串 分割成字符串数组 并动态添加到指定ID的DOM 里

    JS /* * 字符串 分割成字符串数组 并动态添加到指定ID的DOM 里 * @id 要插入到DOM元素的ID * * 输入值为图片URL 字符串 * */ function addImages(i ...

  3. sql server 将字符串分割成表函数 strsplitetotable

    在sql server里,调用存储过程时,经常需要将数据拼成字符串做为参数调用存储过程,而在储存过程中分割字符串虽然简单但麻烦,封装了该函数,可以将拼串分割成内存表返回,方便使用,返回的表字段从a,b ...

  4. SOLOv 2:实例分割(动态、更快、更强)

    SOLOv 2:实例分割(动态.更快.更强) SOLOv2:  Dynamic, Faster and Stronger 论文链接: https://arxiv.org/pdf/2003.10152. ...

  5. PHP+Mysql+easyui点击左侧tree菜单对应表名右侧动态生成datagrid加载表单数据(二)

    关于tree菜单生成,参考我的另一篇博文地址tree 菜单 实现功能:点击左侧tree菜单中的table,右侧通过datagrid加载出该表对用的所有数据 难点:获取该表的所有列名,动态生成datag ...

  6. js 字符串分割成字符串数组 遍历数组插入指定DOM里 原生JS效果

    使用的TP3.2 JS字符串分割成字符串数组 var images='{$content.pictureurl} ' ;结构是这样 attachment/picture/uploadify/20141 ...

  7. oracle根据分隔符将字符串分割成数组函数

    --创建表类型 create or replace type mytype as table of number;--如果定义成varchar--CREATE OR REPLACE type myty ...

  8. SQL Server单表已700w+将普通表转换成分区表1

    最近项目中,某个表数据量爆发时增长,单表已700w+,读写性能急剧下降,所以考虑加入分区表以解燃眉之急,后续还是要分表分库,当然这是后话.下面简要说一下将普通表转为分区表的步骤.   一.创建文件组 ...

  9. MySQL数据库中,将一个字段的值分割成多条数据显示

    本文主要记录如何在MySQL数据库中,将一个字符串分割成多条数据显示. 外键有时是以字符串的形式存储,例如 12,13,14 这种,如果以这种形式存储,则不能直接与其他表关联查询,此时就需要将该字段的 ...

随机推荐

  1. 数据分析(7):pandas介绍和数据导入和导出

    前言 Numpy Numpy是科学计算的基础包,对数组级的运算支持较好 pandas pandas提供了使我们能够快速便捷地处理结构化数据的大量数据结构和函数.pandas兼具Numpy高性能的数组计 ...

  2. linux man的使用

    在Linux中无论是管理系统还是在Linux环境下编程,内嵌的手册man都是一个很好用的工具,“Linux下不懂得就找man”(man是manual的意思).本文将介绍我所知道的所有关于man的知识( ...

  3. CC2530使用串口下载(SBL)

    工作环境: WIN7 64位 IAR 版本: 8.10.3 (8.10.3.10338) ZStack-CC2530-2.3.1-1.4.0协议栈,下载地址:http://download.csdn. ...

  4. hive学习笔记

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  5. Redis——学习之路三(初识redis config配置)

    我们先看看config 默认情况下系统是怎么配置的.在命令行中输入 config get *(如图) 默认情况下有61配置信息,每一个命令占两行,第一行为配置名称信息,第二行为配置的具体信息.     ...

  6. wpf 仿QQ图片查看器

    参考博客 WPF下的仿QQ图片查看器 wpf图片查看器,支持鼠标滚动缩放拖拽 实现效果 主要参考的WPF下的仿QQ图片查看器,原博主只给出了部分代码. 没有完成的部分 1.右下角缩略图是原图不是缩略图 ...

  7. Android Handler消息传递机制

    在Android系统中,类Handler主要有如下两个作用. 在新启动的线程中发送消息. 在主线程中获取.处理消息. 类Handler在实现上述作用时,首先在新启动的线程中发送消息,然后在主线程中获取 ...

  8. seajs学习一天后的总结归纳

    公司项目最近需要将js文件迁移到seajs来进行模块化管理,由于我以前主要接触模块化开发是接触的AMD规范的requireJS,没有接触过CMD规范,而且在实际项目中还没有用过类似技术.于是,我非常兴 ...

  9. linux下memcached安装以及启动

    1. 准备安装文件 下载memcached与libevent的安装文件 http://memcached.googlecode.com/files/memcached-1.4.15.tar.gz(me ...

  10. MongoDB和Redis-NoSQL数据库-文档型-内存型

    1NoSQL简述 CAP(Consistency,Availabiity,Partitiontolerance)理论告诉我们,一个分布式系统不可能满足一致性,可用性和分区容错性这三个需求,最多只能同时 ...