sql - 为性能选择索引和主键

标签 sql database performance postgresql database-design

我是数据库设计的新手,在为战斗游戏设计 PostgreSQL 数据库时遇到了很多麻烦。

在这个游戏中,玩家将在他们之间进行战斗,获得资源来购买更好的武器和盔甲。战斗将被记录下来以备将来审查,预计战斗的数量将迅速增长,例如,1k 名玩家战斗 1k 回合将产生 500k 记录。

游戏交互性降低,需要花费点数来升级战士的装备和能力。战斗由机器解决。

详细信息:

  • 每个战士只能拥有一次特定类型的武器或盔甲。
  • 战士将几乎完全通过 id 进行搜索。
  • 我经常需要搜索特定战士拥有哪些装备(武器和/或盔甲),但我不希望搜索哪些战士拥有特定类型的武器。
  • 通常会按获胜者失败者搜索战斗。
  • 两个给定的 fighters 可以在不同的日期进行多次战斗,因此元组 winner-losercombats 表中不是唯一的
  • fighters 表包含很多列,这些列通常会同时被检索(我创建了两个“Fighter”类的对象,其中包含战斗开始时的所有相关信息)

这是我目前的设计:

CREATE TABLE IF NOT EXISTS weapons (
    id serial PRIMARY KEY,
    *** Game stuff ***
);

CREATE TABLE IF NOT EXISTS armors (
    id serial PRIMARY KEY,
    *** Game stuff ***
);

CREATE TABLE IF NOT EXISTS fighters (
    id serial PRIMARY KEY,
    preferred_weapon INT references weapons(id),
    preferred_armor INT references armors(id),
    *** Game stuff ***
);

CREATE TABLE IF NOT EXISTS combats (
    id serial PRIMARY KEY,
    winner INT references fighters(id),
    loser  INT references fighters(id),
    *** Game stuff ***
);

CREATE TABLE IF NOT EXISTS fighters_weapons (
    fighter INT NOT NULL references fighters(id),
    weapon INT NOT NULL references weapons(id),
    PRIMARY KEY(fighter, weapon)
);

CREATE TABLE IF NOT EXISTS fighters_armors (
    fighter INT NOT NULL references fighters(id),
    armor INT NOT NULL references armors(id),
    PRIMARY KEY(fighter, armor)
);

我的问题是:

  1. 你觉得我的设计合适吗?
  2. 我见过很多包含 id 列作为每个表主键的示例数据库。有什么理由吗?我应该这样做而不是我在 fighters_weaponsfighters_armors 上使用的多列主键吗?
  3. PostgreSQL 会自动为每个主键创建索引,但有几个表我不希望通过它来搜索(即 combats)。我应该删除索引以提高性能吗? PostgreSQL 提示现有约束。
  4. 因为我将搜索fighterfighters_weaponsfighters_armors,以及winner 的combats loser,你认为我应该为这些表的所有这些列创建索引吗?
  5. 任何性能改进建议?最常用的操作是:插入和查询战斗机、查询给定战斗机的设备以及插入战斗。

非常感谢:)

最佳答案

要解决您的明确问题:

2) 最好使用“自然”值作为主键,即不是序列号,如果存在的话。如果您不太可能使用序列号作为标识符,我会说最好不要添加它。

3) 除非您打算非常快速地向 combats 表中插入许多行,否则在 id 列上建立索引可能不会对您造成太大伤害。

4) 如果索引 {fighter, weapon} 存在,则无需在 {fighter} 上创建索引,类似地,如果索引 {fighter, armor} 存在,则无需在 {fighter} 上创建索引。通常,您不会从创建作为另一个多列索引前缀的索引中受益。另外,考虑到您所描述的访问模式,为战斗创建 {winner} 和 {loser} 索引似乎是个好主意。

5) 除了表设计之外,如果您自己安装了数据库,您可能还需要设置一些数据库调优参数。如果有经验的数据库管理员设置了数据库,他/她可能已经为您完成了。

关于sql - 为性能选择索引和主键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14960801/

相关文章:

Mysql限制当整个列表可能改变

php - Codeigniter 预订功能 - 每天限制预订 1 小时

php - 优化我的数据结构。处理大量单位和转换

mysql - 如何在 where 子句中使用 select 中的变量

php - MySQL .sql 导入计划

sql - PostgreSQL。改善指标

c# - 必须声明标量变量 "@campusVisitDate"

java - 当 “parent” 表具有复合 PK 时,如何在 JPA 中建模一对多关系?

javascript - 如何提高JS函数式代码的性能

r - 如何检查一个向量是否是斐波那契数列