2015年8月7日星期五

内存中OLTP(Hekaton)的排序警告 - Woodytu

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
内存中OLTP(Hekaton)的排序警告 - Woodytu  阅读原文»

内存中OLTP是关于内存中的一切。但那只是对了一半。在今天的文章里我想给你展示下,当你从内存读取数据时,即使内存中OLTP也会引起磁盘活动。这里的问题是执行计划里,不正确的统计信息与排序(sort)运算符的组合。

排序(sort)运算符问题

我们都知道,排序(sort)运算符需要所谓的内存授予(Memory Grant)来作它的运行。内存区域是用来进行执行计划里到来记录的排序。内存授予的大小是基于估计行数数量。在基数计算(Cadinality Estimation)期间查询优化器估计执行计划里每个运算符的预计行数。

我在今年6月写了篇文章,展示了当估计错误时,排序(sort)运算符如何能溢出到TempDb。在内存中OLTP里同样的事情会发生:当估计行数错误时,在执行计划里有排序(sort)运算符,排序(sort)运算符会溢出到TempDb!我们来重现这个情形。

内存中OLTP溢出到TempDb

我们新建一个有内存中OLTP文件组配置的新数据库。

1 -- Create new database
2 CREATE DATABASE HashCollisions
3 GO
4
5 -- Add MEMORY_OPTIMIZED_DATA filegroup to the database.
6 ALTER DATABASE HashCollisions
7 ADD FILEGROUP InMemoryOLTPFileGroup CONTAINS MEMORY_OPTIMIZED_DATA
8 GO
9
10 USE HashCollisions
11 GO
12
13 -- Add a new file to the previously created file group
14 ALTER DATABASE HashCollisions ADD FILE
15 (
16 NAME = N'InMemoryOLTPContainer',
17 FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.SQL2014\MSSQL\DATA\InMemoryOLTPContainer'
18 )
19 TO FILEGROUP [InMemoryOLTPFileGroup]
20 GO

下一步我创建新的内存优化表:

1 -- Create a test table
2 CREATE TABLE Table1
3 (
4 Column1 INT IDENTITY,
5 Column2 INT
6 CONSTRAINT pk_Column1 PRIMARY KEY NONCLUSTERED HASH (Column1) WITH (BUCKET_COUNT = 1)
7 ) WITH
8 (
9 MEMORY_OPTIMIZED = ON,
10 DURABILITY = SCHEMA_ONLY
11 )
12 GO

从表定义可以看到,我在Column1列创建了1个哈希索引。因为它是个哈希索引,你也需要指定哈希表上你想拥有的哈希桶数。这里我指定了1个哈希桶,这是个非常,非常糟的做法。当你往表里插入记录时,因为只有1个哈希桶,你会得到巨大数量的哈希冲突(hash collisions)。一般来说,在你定义你的哈希索引的列上,哈希桶数应该和你列上的唯一值个数一致。下面代码往刚才创建的表里插入14001条记录。

1 -- Insert 14001 records
2 INSERT INTO Table1(Column2) VALUES (1)
3
4 SELECT TOP 14000 IDENTITY(INT, 1, 1) AS n INTO #Nums
5 FROM
6 master.dbo.syscolumns sc1
7
8 INSERT INTO Table1 (Column2)
9 SELECT 2 FROM #nums
10 DROP TABLE #nums
11 GO

你可以通过DMV sys.dm_db_xtp_hash_index_stats查看哈希冲突数。从这个DMV的输出可以看到,你有14001条记录在这个且唯一的哈希索引的哈希桶上。现在我们来运行执行计划里有排序(sort)运算符的SELECT语句。

1 -- The sort operator in this execution plan spills over to TempDb!
2 SELECT * FROM Table1
3 ORDER BY Column1

现在当你查看执行计划时,你会看到排序运算符已经溢出到TempDb。

解析大型.NET ERP系统 十三种界面设计模式 - James Li  阅读原文»

成熟的ERP系统的界面应该都是从模板中拷贝出来的,各类功能的界面有规律可遵循。软件界面设计模式化或是艺术性的创作,我认可前者,模式化的界面客户容易举一反三,降低学习门槛。除了一些小部分的功能界面设计特殊一些,ERP绝大部分的功能的界面都相似。以我接触和设计的ERP系统,总结常见的界面设计模式,供读者参考。

模式1 单据 Entry

常用于各种单据的输入界面,也可用于主文件/主档(客户,供应商,部门等)界面,参考下面的图片。

image

我在图中作了标识,A区是工具条按钮,所有的界面共享工具条按钮,接着是数据输入区,数据输入分为主表和明细表。

主表中关键的字段放在界面最顶层,其它各字段根据功能相似的类别组合在一起,B区中除了放置表头数据,还需要用新增加选项卡的方式放置明细数据。C区是单据状态栏,上图中显示了当前单据的创建时间和创建人,也可以增加显示当前单据的状态(未审核,未过帐)。D区是功能状态栏,显示与当前功能关联最重要的会计期间,登入用户和帐套等信息。

模式2 单据查询 Enquiry

这是第一个界面的只读版,去掉了工具条中的新增,删除和编辑功能。代码的实现也非常容易,只需要设定相关属性。

public class PurchaseOrderEnquiry: Sales.PurchaseOrderEntry
{
public PurchaseOrderEnquiry()
{
this.SupportAdd=false;
this.SupportDelete=false;
this.SupportEdit=false;
}
}

模式3 数据查询 Query

这种模式常用来作数据列表查询,上面的两个界面解决了单个数据的编辑,另一种情景中我们常常想要一个列表查询(List),看一下根据指定的过滤条件看一下系统有多少笔数据。

image

数据查询界面设计模式包含四个部分,A区是过滤条件,B区是按钮动作,可以执行查询或是清除A区的过滤条件,C区是数据结果呈现区域,D区是插足结果浏览,打印或是导出Excel。

这个界面模式中的C区结果数据带有钻取功能,看上图中的User Id列,带有蓝色的下划线,双击可以进入指定的功能。

模式4 功能操作 Perform Action

ERP系统中有一部分功能是为了执行一项数据操作,比如日历初始化功能,根据用户输入的日期范围生成日历数据。

这部分界面简单,只需要放置相应的控件,从控件中取值之后执行数据操作。

参考下面的数据存档功能的界面,选择要存档的单据类型,点击处理(Process)即可执行单据存档操作。

image

Perform Action模式因为是完全自定义的界面,所以要用后台线程组件(BackgroundWorker)处理按钮事件(Process中的事件)避免死锁主界面,执行过程中光标也应该是等待状态(Cursors.Waiting)。

模式5 批次处理(过帐,批核) Batch Process(Posting,Approve)

批次处理界面用于简化单据通用操作,比如需要将今天各部门提交上来的物料采购申请一次性或部分的批核完成。将销售订单部分全部过帐完成。通用的操作界面方便了管理层对数据的操作。

image

批次处理功能分五个区,A区是数据过滤条件区,用于输入过滤条件,B区是根据A区中的过滤条件查询到的未过帐的数据,C区是B区中的每笔数据的显示,最后,通过D区中的全选或反选,点击处理(Process)按钮,完成批次处理。

E区可以对B区中的数据进行浏览,或是打印,导出。

这个界面模式与模式3操作相似,先根据过滤条件得到数据,再进行数据操作。

再举一个批次申请加班的例子,参考下面的图片,用于批次申请员工加班。

image

A区是过滤条件区,用于选择一个部门或是班次的一组员工,B区是根据过滤条件得到的员工列表,在C区中填写员工加班的开始时间和结束时间,最后点击D区中的处理(Process)按钮,批次生成加班记录申请表。

模式6 Excel导入 Excel Import

这种模式用于单据的Excel数据文件导入,即使是上线完成,ERP系统中也会包含一部分从Excel导入的功能和数据。

具体见我的文章《解析大型.NET ERP系统 设计通用Microsoft Excel导入功能》,这篇文章中详细讲到了这种模式。

image

这种模式包含三个区域,A区是模板操作区,比如新建,保存或是加载现有的模板,B区是模板的预览结果,将模板导出到Excel文件,按照栏位顺序要求一次填入数据,最后到C区中,选择包含数据的Excel文件,执行导入。

对于非通用的Excel导入,界面设计稍微有所区别,参考下面的图片。

image

非标准化的Excel导入功能包含三个区域,A区选择Excel文件,B区显示A区中选择的文件的数据,相当于预览数据,C区执行导入数据,导入完成后会提示导入成功和失败的数据项,C区还提供一个模板导出功能,方便用户填写数据。

模式7 大量更改 Mass Change

这个模式来源于ERP中的大量工程更改。对已经发行的物料清单要作出调整,需要用ECN(Engineering Change Notice)功能完成。大量工程更改是ECN的批次处理方法实现。ECN每次只能选一个物料清单,而大量工程更改可以根据过滤条件,选择一个范围内的物料清单对它们进行修改(增减物料或工序)。

image

大量更改设计模式随业务不同稍微有所变化,但大致如上图所示分为四个区域。A区是过滤条件,B区是要执行的动作,比如对物料清单增加物料或删除工序,C区中有一些选项卡,用于显示受影响的数据,这样让用户可以知晓哪些数据会被修改。D区是执行修改动作。四个区域的设计,由过滤条件(A)到受影响的数据(C),增加要执行的动作(B),最后执行。

模式8 数据查找 Lookup

数据查找窗体用于简化数据输入,提供系统可用性。比如输入供应商时,可以弹出供应商选反对话框,输入客户编号的地方,可以弹出客户编号对话框。

image

数据查找窗体设计模式包含三个区域,A区是数据结果区,显示满足条件的查询数据,B区可以对A区的数据进行搜索,借助于Infragistics WinGrid的功能,A区也可以对数据进行搜索,重排序,分组,统计(求和,求数量,求平均值),C区是确定按钮,用于返回A区中光标所选中的行。

以上是单一数据查找窗体,参考下面的多笔数据查询窗体,支持选择一行或多行数据,只是在C区中多增加了几个按钮。

image

相比于前面的图片,上图中的图片多了两个选择项按钮。

模式9 附件 Attachment

ERP功能中的单据支持附件管理,比如客户主档功能中,将客户的资质等信息以附件文档的形式保存在客户主档功能中。每次想查看客户的资料,直接从系统中查看附件。

具体见我的文章《解析大型.NET ERP系统 通用附件管理功能》,这篇文章中详细讲到了这种模式。

image

附件管理功能界面包含四个区域,A区是工具条,用于增删改单据的附件数据,B区是单据的附件数据列表,C区是B区的附件文件浏览窗口,D区用于对C区的附件文件进行操作。可另存到本机或是在操作系统进程中打开附件文件。

附件界面设计模式中,附件文件可以保存在数据库,共享文件夹或是FTP服务器中,这样D区的实现代码会因存储位置的不同,稍微有所变化。

模式10 报表 Report

ERP系统包含数量庞大的报表库,设计一个通用的报表阅读界面给系统增色不少,报表界面支持常见的报表操作(打印,导出,缩放尺寸,

阅读更多内容

没有评论:

发表评论