什么是更高效(在查询性能方面)数据库表设计 - 长还是宽?
即,这个
id size price
1 S 12.4
1 M 23.1
1 L 33.3
2 S 3.3
2 M 5.3
2 L 11.0
与此
id S M L
1 12.4 23.1 33.3
2 3.3 5.3 11.0
一般来说(我估计)它归结为GROUP BY
与直接选择列之间的性能比较:
SELECT AVG(price) FROM table GROUP BY size
或
SELECT AVG(S), AVG(M), AVG(L) FROM table
第二个写入时间稍长(就多列而言),但两者的性能如何呢?如果可能,每种表格格式的一般优点/缺点是什么?
答案 0 :(得分:6)
首先,这些是适用于不同目的的两种不同的数据模型。
话虽如此,我希望 1 第二个模型的聚合速度更快,因为数据打包更紧凑,因此需要更少的I / O:
{size, price}
上的完整扫描来满足。当数据太大而无法容纳在RAM中时,索引的替代方法太慢了。由于第一种方法需要table + index而第二种方法只需要表,因此在第二种情况下缓存利用率更高。即使我们忽略缓存并将第一个模型中的索引(没有表)与第二个模型中的表进行比较,我怀疑索引会比表大,只是因为它物理记录size
并且未使用B树的典型“洞”(如果是clustered,表格也是如此)。
最后,第二个模型没有索引维护开销,这可能会影响INSERT / UPDATE / DELETE性能。
除此之外,您可以考虑在仅包含一行的单独表中缓存SUM和COUNT。每当在主表中插入,更新或删除行时,都会通过触发器更新SUM和COUNT。然后,只需将SUM和COUNT分开即可轻松获得当前的AVG。
1 但是你应该确实衡量代表性的数据量。
2 由于查询中没有WHERE子句,因此将扫描所有行。索引仅用于获取表的行的相对较小的子集(有时用于index-only scans)。作为一个粗略的经验法则,如果需要表中超过10%的行,索引将无济于事,即使索引可用,DBMS也会选择全表扫描。
答案 1 :(得分:2)
第一个选项会产生更多行,并且通常比第二个选项慢。
然而,正如Deltalima所说,第一种选择更灵活。不仅在涉及不同的查询选项时,而且当您/有一天需要使用其他尺寸,颜色等扩展表时。
除非您拥有非常大的数据集或需要超快的查找时间,否则第一个选项可能会更好。
如果您确实拥有或需要非常大的数据集,最好创建一个包含预先计算的汇总值的表格。
答案 2 :(得分:1)
长期使用更灵活。它允许您过滤size
例如
SELECT MAX(price) where size='L'
它还允许在size
和id
上建立索引。这会加快GROUP BY
以及id
和/或size
此类产品库存表中其他表格加入的任何查询。