DataTable缓存性能





5.00/5 (8投票s)
本项目实现了 DataTable 的缓存,并提供了性能测试功能。
引言
在 .NET Framework 4 中,存在 `System.Runtime.Caching.MemoryCache` 类。 `DataTable`s 可以存储在该缓存中,以便检索时访问这些缓存的 `DataTable`s 而不是数据库。 正如将要展示的,对于记录数不超过大约 1000 条的表,这样做是有意义的。 需要 SQL Server 数据库。
背景
在许多程序中,`SqlDataAdapter.Fill` 方法用于从数据库检索数据并将其存储在 `DataSet` 中。 频繁访问但很少更改的表可以存储在内存中以加快数据访问速度。 `MemoryCache` 类提供了 `Add` 方法,可以使用该方法在某个键下添加任何对象。 在本项目中,`DataTable`s 被添加到 `MemoryCache`。 当要从表中检索记录时,会检查该表是否存在于缓存中。 如果存在,则从缓存中检索 `DataTable`,否则从数据库中检索并将其存储在缓存中。 `DataTable` 中的记录使用 `DataView` 的 `RowFilter` 属性查找。
性能通过一系列测试套件进行测试。 测试套件的表大小从 100 条记录到 2000 条记录不等。 每个测试套件向 "Items" 表添加 100 条随机记录,然后在没有缓存的情况下每秒检索一条记录,然后再使用缓存进行检索。 每秒检索次数将被计数并显示在网格中。
解决方案
- 使用 Visual Studio 2010 打开 _Tests.Cache.vbproj_,然后生成并运行它。 将出现以下窗体
- 在“连接字符串”文本框中,必须定义到数据库的连接字符串。 数据库必须是 SQL Server。
- 选择菜单“文件/重新创建表”。 这将在数据库上重新创建 "Items" 表。
- 按“准备测试套件”按钮。 这将为每个测试套件生成列标题。"随机数数量"文本框定义了从一个测试套件到下一个测试套件的表大小增量。"最大表大小"文本框定义了最后一个测试套件的表大小。
- 通过按“运行测试套件”按钮,测试套件将被执行。 每秒检索次数将写入网格。
- 打开提供的 Excel 文件 _CacheNotes.xlsx_。
- 将网格中的结果复制粘贴到 Excel 文件中。 更具体地说,从网格中复制 Items_Id = 1 和 2 的行,从第 4 列(标题为“100:4”)开始,复制到 Excel 文件第 5 行和第 6 行的 B 列及之后(Excel 坐标为 B5-U6)。
- 查看 Excel 文件中的图表。 最有可能的是,在第一个图表中,浅蓝色线(带缓存)在深蓝色线(不带缓存)之上,而在第二个图表中,情况则相反。
故障排除
保存到数据库并从数据库加载
您可能想测试保存到数据库和从数据库加载是否正常工作。
- 通过菜单“文件/重新创建表”重新创建 "Items" 表。
- 通过选择菜单“文件/添加随机”向网格添加 100 条随机记录。
- 通过按“保存到 db”按钮将记录保存到数据库。
- 通过菜单“文件/清除”清除网格内容。
- 通过按“从 db 加载”按钮从数据库加载记录。
测试缓存
要测试缓存,必须在数据库中存在一些数据,例如以上步骤已成功完成。
- 通过按“加载”按钮,数据将从缓存加载。 如果数据尚未在缓存中,则从数据库加载。
- 通过按“缓存键”按钮查看缓存项。
- 通过按“清空 db”按钮删除数据库中的数据。
- 点击“加载”按钮,并验证即使数据库中不存在数据,数据仍然可以从缓存加载。
- 通过点击“清除缓存”按钮清除缓存。
- 点击“加载”按钮,并验证没有数据加载到网格中。
性能测试
要测试性能,数据库中必须存在一些数据。
- 要在一秒钟内重复从数据库检索所有记录,请按“重复从 db 加载”按钮。 一秒钟后,消息框将指示完成的迭代次数。
- 要在一秒钟内重复从缓存检索所有记录,请按“重复加载”按钮。 一秒钟后,消息框将指示完成的迭代次数。
测试套件
一个测试套件包含多个测试用例。 例如,一个测试套件测试一次带缓存和一次不带缓存的记录检索。 但是,代码通过组合三个维度来支持每个测试套件的多个测试用例
- 选择标准: `ModCache.GetTestCriteria()` 方法可以返回多个不同的选择标准,例如
- Items_Id=2
- Name='abc'
- 数据访问类:可以有多个数据访问类。 这些类定义在 `DBAccess.DataAccessClasses` 中。
- 缓存测试:带缓存和不带缓存。
准备和运行测试用例
- 选择菜单项“选项/填充测试套件”为上述三个维度的所有可能组合准备一个测试套件。
- 按“运行测试套件”按钮来运行测试套件。 这将在一秒钟内重复运行每个测试用例,并将迭代次数写入网格。
代码文档
- _Form1.vb_:这是带有网格、菜单和按钮的主窗体。
- 绑定:除“准备测试套件”和“运行测试套件”之外的所有操作都会操作绑定到网格的数据集 `ItemsData1`。“准备测试套件”和“运行测试套件”操作会取消网格与数据集 `ItemsData1` 的绑定,并直接操作网格。
- 并行化:在性能测试期间,重复的请求以尽可能多的线程并行运行,如“线程数”文本框中所指定。 有两种不同的方法来实现并行请求。
- `ParallelFor`:使用 .NET 的 `Pararallel.For` 语句。
- `ParallelThreads`:创建所需数量的线程。
- _DBAccess.vb_:封装了不同数据访问类的所有数据库功能。 在此版本中,提供了一个数据访问类 `MySQLDataAccess`。 但是,一个更大的项目可能还有其他数据访问类,例如一个在 COM+ 下运行的数据访问类和一个不在 COM+ 下运行的数据访问类。 查看 `DataAccessComPlus` 和 `DataAccessNonComPlus` 的注释,了解其他数据访问类如何集成到这里。
- _ItemsData.xsd_:用作用户界面的底层数据结构,并用于将数据加载到数据库和从数据库保存数据。 它的结构与“重新创建表”菜单项创建的 "Items" 表的结构相同,后者又使用了在资源 `SqlCreateTableItems` 中定义的 SQL 语句。
- _ModCache.vb_:提供了一些与缓存相关的函数。 最重要的是 `FillDataSetFromDataTable`,它通过在 `DataTable` 上创建 `DataView` 并设置 `DataView` 的 `RowFilter` 和 `Sort` 属性来搜索 `DataTable` 中的记录。 这段代码是缓存记录数超过 1000 条的表不值得的原因,因为对于大表来说,创建 `DataView` 并在 `DataView` 中搜索比在数据库中搜索更慢。
- _MySQLDataAccess.vb_:一个提供数据库数据访问的类。 可以实现其他类,并将它们添加到 DBAccess 中。