sql - 非常庞大的 SQL 数据库 : How should the schema look like?

标签 sql database schema

我有 2 个文件要导入到 MS SQL 中。第一个文件是 2.2 GB,第二个文件是 24 GB 的数据。 (如果你好奇:这是一个扑克相关的查找表)

将它们导入 MS SQL 不是问题。感谢 SqlBulkCopy,我能够在短短 10 分钟内导入第一个文件。我的问题是,我不知道实际的表架构应该是什么样子才能让我进行一些非常快速的查询。我的第一个天真的尝试是这样的:

CREATE TABLE [dbo].[tblFlopHands](
    [hand_id] [int] IDENTITY(1,1) NOT NULL,
    [flop_index] [smallint] NULL,
    [hand_index] [smallint] NULL,
    [hs1] [real] NULL,
    [ppot1] [real] NULL,
    [hs2] [real] NULL,
    [ppot2] [real] NULL,
    [hs3] [real] NULL,
    [ppot3] [real] NULL,
    [hs4] [real] NULL,
    [ppot4] [real] NULL,
    [hs5] [real] NULL,
    [ppot5] [real] NULL,
    [hs6] [real] NULL,
    [ppot6] [real] NULL,
    [hs7] [real] NULL,
    [ppot7] [real] NULL,
    [hs8] [real] NULL,
    [ppot8] [real] NULL,
    [hs9] [real] NULL,
    [ppot9] [real] NULL,
 CONSTRAINT [PK_tblFlopHands] PRIMARY KEY CLUSTERED 
(
    [hand_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

翻牌指数是一个从1到22100的数值(德州扑克中前3张普通牌,52选3)。每个翻牌索引都有一个从 1 到 1176 的 hand_index(49 选择 2)。因此,此表中总共有 25,989,600 行。

用我上面的“模式”做一个查询大约花了。 25 秒。经过一番谷歌搜索后,我发现 SQL 服务器正在执行表扫描,这显然是一件坏事。我运行了“Database Engine Tuning Advisor”,它建议在 flop_index 列上创建一个索引(有意义)。创建索引后,数据库所需的磁盘空间正好翻了一番! (加上日志 LDF 文件增长了 2.6 GB) 但是在索引之后,查询只需要几毫秒。

现在我的问题是,我应该如何以正确的方式进行操作?我从来没有处理过如此庞大的数据,我之前创建的数据库简直就是个笑话。

一些注意事项:将数据导入 MS SQL 后,将永远不会插入或更新数据,只有选择。所以我想知道我是否需要主键?

编辑:我提供了更多信息以使我的问题更清楚:

1) 我永远不会使用 hand_id。我把它放在那里是因为很久以前有人告诉我,我应该总是为每个表创建一个主键。

2) 基本上我只会使用一个查询:

SELECT hand_index, hs1, ppot1, hs2, ppot2, hs3, ppot3, hs4, ppot4, hs5, ppot5, hs6, ppot6, hs7, ppot7, hs8, ppot8, hs9, ppot9 WHERE flop_index = 1...22100

此查询将始终返回 1176 行我需要的数据。

EDIT2: 更具体地说:是的,这是静态数据。我将此数据保存在二进制文件中。我已经编写了一个程序,可以在几毫秒内用我需要的数据查询这个文件。我希望将此数据保存在数据库中的原因是我希望能够从网络中的不同计算机查询数据,而无需在每台计算机上复制 25 GB。

HS 表示牌力,它告诉您当前底牌与翻牌或转牌相结合的牌力。 ppot 表示正潜力,这是下一张公共(public)牌发完后您的手牌领先的机会。 hs1 到 9 是对抗 1 到 9 对手的牌力。 ppot 也一样。即时计算 ppot 非常占用 CPU,需要几分钟的时间来计算。我想创建一个扑克牌分析程序,它会为我提供在任何给定的翻牌/转牌及其 hs/ppot 上所有可能的底牌组合的列表。

最佳答案

要回答有关需要主键的问题 - 仅使用您在问题中提供的信息:

根据您的表架构,您不妨将其保留在那里。如果您删除该标识列,您也将删除您的聚簇索引。您的聚集索引值(4 个字节)存储为每个非聚集索引行中的指针。通过删除该聚簇索引,您会将表保留为堆——SQL 将为表中的每一行创建一个 8 字节的 RID(行标识符),并将其用作非聚簇索引中的指针。因此,在您的情况下,根据您在问题中提供的架构 - 您可能会增加非聚集索引的大小,并最终减慢它们的速度。

综上所述 - 基于问题中未包含的您可能正在运行的查询(及其使用模式) - 将聚簇索引评估为身份列以外的其他内容也可能符合要求.

关于sql - 非常庞大的 SQL 数据库 : How should the schema look like?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1359047/

相关文章:

sql - 除了自加入还有其他选择吗

mysql - 更新查询在同一 id 未提及的行中插入 null

mysql - SQL查询以查找连接表行的计数作为每行的摘要

php - 在 Woocommerce 中以编程方式添加新产品类别

c# - 从 XElement 创建带有命名空间和架构的 XML

sql - 将 mm、dd 和 yr 的单独列转换为可用的 mm/dd/year 格式

c++ - 如何将用户输入的数据从 datagridview 获取到 Windows 窗体图表?

MySQL:根据另一行更新多行的列

postgresql - 如何将许多表从一个模式自动移动到 PostgreSQL 中的另一个模式?

schema - 在多维数据集中合并 2 个事实?