gpt4 book ai didi

MySQL:长表与宽表

转载 作者:可可西里 更新时间:2023-11-01 06:36:43 38 4
gpt4 key购买 nike

什么是更高效(就查询性能而言)的数据库表设计 - 长表还是宽表?

即,这个

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

第二个写的有点长(就很多栏目而言),但是两者的性能如何呢?如果可能,每种表格格式的一般优点/缺点是什么?

最佳答案

首先,这是两种适用于不同目的的不同数据模型。

话虽如此,我预计1第二个模型的聚合速度会更快,因为数据打包得更紧凑,因此需要更少的 I/O:

  • 第一个模型中的 GROUP BY 可以通过对索引 {size, price} 进行完整 扫描来满足。当数据太大而无法放入 RAM 时,替代索引的速度太慢。
  • 第二个模型中的查询可以通过全表扫描来满足。不需要索引2

由于第一种方法需要表+索引,而第二种方法只需要表,因此第二种情况下缓存利用率更高。即使我们忽略缓存并将第一个模型中的索引(没有表)与第二个模型中的表进行比较,我怀疑索引会比表大,仅仅是因为它物理上记录了 size并且具有 B 树典型的未使用“孔”(尽管对于表也是如此,如果它是 clustered )。

最后,第二种模型没有索引维护开销,这可能会影响 INSERT/UPDATE/DELETE 性能。

除此之外,您可以考虑将 SUM 和 COUNT 缓存在仅包含一行的单独表中。每当在主表中插入、更新或删除行时,都会通过触发器更新 SUM 和 COUNT。然后,您只需将 SUM 和 COUNT 相除即可轻松获得当前的 AVG。


1 但您确实应该测量有代表性的数据量才能确定。

2 由于您的查询中没有 WHERE 子句,因此将扫描所有行。索引仅对获取相对较小的表行子集有用(有时用于 index-only scans )。作为一个粗略的经验法则,如果需要表中超过 10% 的行,索引将无济于事,即使索引可用,DBMS 通常也会选择全表扫描。

关于MySQL:长表与宽表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16026226/

38 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com