0

我想设计一个快速的数据库模式,它可以处理排序和过滤列以及更新条目。

为此,我创建了以下场景:

  • 一个事件只有一个名称、状态、最后订阅日期、描述和一个位置
  • 活动的可用席位数量与活动一起保存,每次参与者订阅时都会更新
  • 每个事件都只有一个类别
  • 事件只能按类别列出
  • 事件可以按名称、状态或日期过滤(无异或)
  • 事件可以按名称、状态或日期(异或)排序
  • 这些表必须处理超过 10 个 mio 条目

对于所有测试,我使用 MySQL 和 InnoDB 表。我还尝试尽可能频繁地使用多个插入/更新/删除。通过使用LIKE '%[word]%'完成过滤

首先,我尝试使用 2 个表:一个用于类别,另一个用于事件。索引是类别名称、类别状态名称、类别日期名称和类别日期状态名称。为此,列出、过滤和排序非常快,但插入、更新或删除条目非常慢。我也遇到了锁超时,因为重建索引花费了太多时间。

第二次尝试是有 3 个表:类别、事件和位置。但是如果位置表包含 6 个或更多条目,它也会变慢。我认为是因为快速捕获的索引。添加 100k 个条目大约需要 272 秒。位置的索引是primary-index idzip-street

下一个尝试是为 last-subscription-date 和计数器创建一个自己的表。但是过滤这个日期或排序这个日期的可能性呢?

最好有 3 个索引,例如:类别名称、类别日期、类别状态,还是我的解决方案有 4 个索引类别名称、类别状态名称、类别日期名称和类别日期状态-为 MySQL命名更好的一个?

我也在考虑字段类型:目前我使用 VARCHAR 作为名称。但也许 CHAR 更好,因为每个条目都具有相同的长度,因此跳转到索引中的特定位置而不是使用可变长度会更快。你怎么看?

有人对如何设计一个支持上述场景的良好和快速的数据库模式有一些建议吗?

4

1 回答 1

1

索引是固定长度的,因此 CHAR 与 VARCHAR 对索引无关紧要,尽管它对表扫描很重要。

如果没有具体细节,我认为我无法提供任何其他明确的答案。我可以给你一些一般性的建议。

您应该避免插入聚集索引(InnoDB 主键或第一个唯一键)。聚集索引通常与自动递增的列一起使用,以便仅将索引附加到其中,而不会在中间插入任何内容。这避免了重建索引。

对于非聚集(二级)索引,索引越大,在插入时必须重新构建的频率就越高。可以执行插入,直到页面填满,然后重新构建。同样,附加到索引的末尾很好。

删除不会影响性能,因为索引只标记为删除,并且在空闲时间重建索引。

不应在基数低的列上创建索引,因为 MySQL 不会使用它们。仅应根据需要添加索引,每次都权衡利弊。

多列索引更大(页面中的条目更少)并且需要更新更多条目。谨慎添加多列索引。

MyISAM 更适合频繁读取,但由于锁争用(表锁),在多用户环境中频繁更新/插入会陷入困境。由于锁争用(行锁)较少,InnoDB 更适合多用户环境中的更新,但读取速度较慢(仍需要行锁)。

表单的过滤LIKE '%[word]%'不能使用索引,但过滤LIKE '[word]%'可以使用索引。

在频繁更新的系统上,索引对于选择记录进行更新和读取记录同样重要。索引越好,锁争用越少,因此性能越好,死锁越少。

JOIN 越多,成本越高,查询越慢。JOIN 还不错,但是多行(大型结果集)上的 JOIN 可能会很慢。

一些与性能无关的警告:

使用 InnoDB,您应该准备好处理由于死锁而导致的失败事务。

于 2012-05-30T17:59:38.563 回答