我将使用我在不久的将来编写的应用程序运行大量模拟,但我在围绕此设计数据库时遇到了麻烦。
这是它的工作原理。每个模拟有 6 个可以变化的参数,每个参数有大约 10 个选项。所以我们有大约 100 万个这样的排列以某种方式存储在数据库中。我能想到的最简单的方法是为每个参数设置一列,并为我的主键 (ExperimentID) 设置一个附加列。然后我可以通过做一个简单的操作来直接访问给定实验的参数
SELECT * FROM Parameters WHERE ExperimentID = (givenID)
Run Code Online (Sandbox Code Playgroud)
每个参数都将作为 int 存储在数据库中,我的应用程序将在运行时将其解释为必要的参数。
一种更复杂但我认为更快的方法是利用二进制移位的速度。我没有直接存储参数,而是将有关每个参数的信息存储在 unsigned int 的 4 位中。我实际上不知道如何在数据库中存储整数(二进制),所以这是主要的阻碍。
在这种情况下该怎么做有什么建议吗?另外,我还没有这些列,所以如果我决定采用第一个选项,我将如何用一组参数的所有排列填充表格?
为什么您认为将真实数据隐藏到位掩码字段中会更快?您只是在谈论 100 万行和每行 24 个字节。这真的不多,特别是因为您只进行单例/查找操作。
更好的优化是使用TINYINT字段(范围为 0 - 255 ;byte在 .NET 中)。使用TINYINT而不是INT(并假设FILLFACTOR**为 100)将导致:
INT字段这里获得的主要效率是:
2244 条记录的初始查找时间更快。为何如此?对于 100 万行,每 8k 数据页 287 行相当于 3484 页,而每 8k 数据页 806 行仅相当于 1240 页。一旦读取页面以获取第一行的值,它应该保留在缓冲池(即内存)中以供后续查找(即同一数据页上的其他行)。每页更多行意味着从磁盘读取的页面更少——在这种情况下减少 2244 页。但是一旦所有页面都在缓冲池中,无论是每页 806 行还是 287 行,查找都应该具有相同的速度。因此,100 万次中的 2244 次查找操作稍微快一些。当然还不错,因为没有与此优化相关的成本,但只是希望对其进行透视。
将整个表保存在内存中所需的内存更少。这将使它更有可能留在内存中。
最后,绝对可以将这些数据压缩成更小的表示。但此时它是每行 10 个字节,处理/编码没有增加任何复杂性,并且所有值都是人类可读的。每行 10 个字节以下没有太多空间,但即使它降至每行 7 个字节(INT IDENTITY + 3 个参数字节,这应该是处理这些范围所需的最小值),我是不确定增加的复杂性是否值得(即规模不经济)。
CREATE TABLE dbo.Experiment
(
ExperimentID INT NOT NULL IDENTITY(1, 1),
Parameter1 TINYINT NOT NULL,
Parameter2 TINYINT NOT NULL,
Parameter3 TINYINT NOT NULL,
Parameter4 TINYINT NOT NULL,
Parameter5 TINYINT NOT NULL,
Parameter6 TINYINT NOT NULL,
CONSTRAINT [PK_Experiment] PRIMARY KEY (ExperimentID) WITH (FILLFACTOR = 100) ON [Tables]
)
ON [Tables];
Run Code Online (Sandbox Code Playgroud)
您可以使用以下内容填充它(假设有两个参数 0 - 4、两个参数 0 - 7 和两个参数 0 - 9 ;基于对问题的评论):
;WITH Five(num) AS
(
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
), Eight(num) AS
(
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7
), Ten(num) AS
(
SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8
UNION ALL SELECT 9
)
--INSERT INTO dbo.Experiment
-- (Parameter1, Parameter2, Parameter3, Parameter4, Parameter5, Parameter6)
SELECT f1.[num] AS [Parameter1],
f2.[num] AS [Parameter2],
e1.[num] AS [Parameter3],
e2.[num] AS [Parameter4],
t1.[num] AS [Parameter5],
t2.[num] AS [Parameter6]
FROM Five f1
CROSS JOIN Five f2
CROSS JOIN Eight e1
CROSS JOIN Eight e2
CROSS JOIN Ten t1
CROSS JOIN Ten t2;
Run Code Online (Sandbox Code Playgroud)
上面的查询仅生成 160k 排列,而不是 100 万,同样基于对问题的评论。但是应该很容易弄清楚如何针对六个参数的任意组合的不同值范围进行调整。
** FILLFACTOR:行存储在大约 8060 字节的数据页上。较小的行 = 适合该固定大小容器的更多行。FILLFACTOR是为新行或由于新版本的行需要更多字节的可变长度字段占用更多空间的更新保留多少空间(在创建/重建索引时)。值 100 表示没有保留空间,8060 的 100% 应由当前行占用。在这种情况下,只有固定长度的字段,没有乱序插入。
| 归档时间: |
|
| 查看次数: |
776 次 |
| 最近记录: |