使用连接来优化sql查询

时间:2012-10-05 13:07:11

标签: sql sql-server performance tsql join

我有一张桌子,可存储近千万行的人的信息。

目前State是person表上的char(2)字段。这会导致大量重复数据,如您所料。如果我将状态数据规范化为它自己的表并在人员表中为它创建一个FK,这会导致更快的查询时间吗?

在:

SELECT Name, City, State FROM Person WHERE State = 'WI'

后:

SELECT p.Name, p.City, s.Name as State
FROM Person p
    INNER JOIN State s ON p.State == s.Id
WHERE s.Name = 'WI'

在我看来,这会提高性能,但在优化查询方面,我远非专家。

6 个答案:

答案 0 :(得分:2)

规范化可以导致降低性能,但在这种情况下很少会提高你的性能,因为现在服务器必须查看两个地方磁盘而不是一个。

规范化有两个目的:

  1. 减少磁盘上存储的数据量
  2. 允许在一个地方更新数据
  3. 您的查询不会受益于

    这些优势
    1. char(2)和int(外键)
    2. 之间没有太大区别
    3. 状态的两位数代码永远不会改变,因此您永远不需要更新它

答案 1 :(得分:1)

如果你只谈论2个字符 - 那么将它拆分成新表可能没用多少。

(但是 - 考虑到允许的特定值域 - 如果有人输入VX或其他一些非允许的值 - 在非规范化时无法正确或有效地约束)

如果你正在谈论其他信息,比如美国邮政abbraviation(2个字符)和州名,可能还有其他一些信息,那么绝对是 - 将它拆开。

作为一种惯例,你应该总是在正确的规范化方面犯错(imo) - 然后在经过冗长的论证之后才应该考虑非规范化。

答案 2 :(得分:1)

如果在状态表上创建一个非常窄的键,如TINYINT,那么 可以提高性能,但不能保证。但这完全值得测试。

考虑制作每个表的副本,正确索引它们,然后使用分析器同时在两个表上运行查询。

最终速度可能会提高1%。

尽管如此,正常化很少是一个坏主意......

答案 3 :(得分:0)

没有太多空间可以保存 您可以在状态表上使用byte(tinyint)作为主键,因为只有50个状态 Char(2)是两个字节 因此,您只需在人员表中每行保存一个字节。

压缩数据的优点是磁盘空间更少,内存也更少 对于固定数量的内存,如果数据较小,则内存中数据的可能性更高。

我不认为1字节的大小差异值得加入的开销。

但我会因为这是一个好习惯而正常化 为什么要让某人进入JZ州?

第三次正常表格失败 Achieve 3NF
如果有重复的组,请将组分为各自的关系。

您可以在状态表中使用char(2)作为PK,因此char(2)与char(2)直接匹配。
这将满足第3范式,因为这些值仅限于50个州 在这种情况下,您不需要加入select,因为实际值在主表中 在插入或更新时,强制执行FK关系,因此它必须是有效状态。

如果您想报告整个州,可以在状态表中添加一个列作为全名。

答案 4 :(得分:0)

嗯..在您的查询中,您正在做一些非最佳的事情。

SELECT p.Name, p.City, s.Name as State
FROM   Person p
       INNER JOIN State s ON p.State == s.Id
WHERE s.Name = 'WI'

您获得所有状态记录的人员详细信息,之后您使用“WI”过滤状态。

如果你试试这个,你的状态就会减少!

SELECT p.Name, p.City, s.Name as State
FROM   Person p
       INNER JOIN State s 
         ON  p.State == s.Id
         and s.Name = 'WI'

为什么呢?因为您只会获取名称为WI而不是所有州列的州列。

之后..如果它适合您的索引,请在name ='WI'的状态下创建一个过滤索引

这会有所帮助..

答案 5 :(得分:-2)

搜索字符串索引(理论上)比搜索int索引要慢得多。这意味着是;规范化您的数据会使其更快。在实践中,我经常看到差异微乎其微;因人而异。您可能必须预先缓存或单独选择状态ID:

SELECT p.Name, p.City, s.Name as State
FROM Person p
INNER JOIN State s ON p.State == s.Id
WHERE s.Id = (select id from State where State.Name = 'WI');

与查询一样,最好进行测试和优化。