SQL动态优化表?

时间:2019-02-13 04:36:41

标签: sql

我是一个非常有经验的程序员,但是对SQL来说是个新手,它对事物的看法比代码中的观点更为有限。我认为一般来说我可能在SQL上下文中看到这个错误,所以我正在寻找方向。我不认为特定的SQL实现在这一点上确实不重要。我认为这只是我遇到的一般SQL概念问题。

这就是我的想法:

假设我要跟踪大量体育赛事的结果(上千万个或更多),其中包括参加比赛的队伍和最终得分:

CREATE TABLE teams (
  TeamID INT NOT NULL PRIMARY KEY,
  TeamName VCHAR(255) NOT NULL
)

CREATE TABLE games (
  GameID INT NOT NULL PRIMARY KEY,
  TeamA INT NOT NULL,
  TeamB INT NOT NULL,
  TeamAScore INT,
  TeamBScore INT, 
  FOREIGN KEY TeamA(TeamID)
  REFERENCES teams (TeamID),
  FOREIGN KEY TeamB(TeamID)
  REFERENCES teams (TeamID)
)

由于“游戏”表将非常大,因此当查询特定团队的结果时,在我看来,同时搜索“ TeamA”和“ TeamB”列以进行匹配可能会非常耗时-消耗操作。反过来,这将使在UI上立即呈现成为问题。

但是,如果有每个团队玩的游戏列表,则查询可以更快(以增加存储量为代价):

CREATE TABLE team_TeamID_games (
  GameID INT NOT NULL,
  FOREIGN KEY GameID(GameID)
)

然后显示团队的结果列表仅涉及使用“ team_TeamID_games”表并直接提取“ games”表的结果,而不是对其进行搜索。

这里有问题的部分始于为每个团队引入新表格的想法。上面“ team_TeamID_games”的“ TeamID”部分将替换为团队ID,因此可能会有名为“ team_1_games”,“ team_2_games”等的表。

仅此一项就与我在研究SQL使用中所见所见相悖。

此外,根据到目前为止我对SQL的了解,实际上没有标准的方法将“ team_TeamID_games”表实际链接到“ teams”表的“ TeamID”行,因为外键引用了行,而不是整个表格。这意味着数据库并不真正知道连接。

或者,可以将另一个表名的VARCHAR()字符串存储在“团队”表中,但是我也不认为这实际上对数据库有任何意义。

  • 在数据库本身之上和之外完成的表之间的链接的概念是一件非常糟糕的事情吗?
  • 为每个团队创建这样的“动态”表(不是预先静态创建,而是在注册团队时创建,并在输入游戏结果时填充)是否是一个坏主意?
  • 还有另一种方法可以完成此优化吗?

1 个答案:

答案 0 :(得分:1)

不确定您认为“非常”大的内容。与例如如果有2500支球队,则结果游戏桌数约为600万行。如今,这甚至不算是“大笔钱”。如果有5000支队伍,游戏桌将有2500万行。如今仍不是“极端”大型。


可以使用以下查询回答“查找特定团队的所有比赛”查询:

select *
from games
where teama = 42
   or teamb = 42;

(通常)可以通过在每列上创建一个索引来改进:

create index idx_team_a on games (teama);
create index idx_team_a on games (teamb);

Postgres(可能还有其他DBMS产品)也可以将两个索引用于该查询。在我的笔记本电脑(拥有2500个团队和620万个游戏)上,查询大约需要3 milliseconds

另一种选择是在涵盖两个团队ID的表达式上创建索引

create index on games ( (least(teama, teamb)) );

该表达式随后可用于查找一个团队的所有比赛:

select *
from games
where least(teama, teamb) = 1234;

a bit faster仅涉及一个索引:在我的笔记本电脑上大约2毫秒。


在2500万行(5000个团队)中,两种方法之间的差异要大一些。 OR查询大约需要15-20毫秒,基于表达式的查询大约需要5-10毫秒。

即使20毫秒似乎也不是UI中的问题。

因此,通过仔细的索引编制,我看不到为什么您需要任何其他表。