我们能否得到一份基本优化技术的列表(从建模到查询、创建索引、视图到查询优化)。最好列出这些,每个答案一种技术。作为一个爱好者,我会发现这非常有用,谢谢。
为了不太模糊,假设我们正在使用主流数据库,例如 MySQL 或 Oracle,并且该数据库将包含大约 10 个表中的 500,000-1m 左右的记录,其中一些具有外键约束,全部使用最典型的存储引擎(例如:InnoDB for MySQL)。当然,还定义了诸如 PK 之类的基础知识以及 FK 约束。
我们能否得到一份基本优化技术的列表(从建模到查询、创建索引、视图到查询优化)。最好列出这些,每个答案一种技术。作为一个爱好者,我会发现这非常有用,谢谢。
为了不太模糊,假设我们正在使用主流数据库,例如 MySQL 或 Oracle,并且该数据库将包含大约 10 个表中的 500,000-1m 左右的记录,其中一些具有外键约束,全部使用最典型的存储引擎(例如:InnoDB for MySQL)。当然,还定义了诸如 PK 之类的基础知识以及 FK 约束。
了解索引,并正确使用它们。一般来说*,请遵循以下准则:
*如果您知道自己在做什么,则这些规则有一些例外。我的经验是 Microsoft SQL Server,但我认为大部分建议仍适用于不同的 RDMS。
IMO,到目前为止,最好的优化是让数据模型适合它所构建的问题域。如果不这样做,则产生的症状是难以编写或复杂的查询,以便获得所需的信息,并且通常在针对数据库构建报告时自行恢复。因此,在设计数据库时,了解用户希望从系统获得的信息(例如报告)的类型和性质是有帮助的。
在谈论数据库设计时,请查看数据库规范化,例如 wikipedia 文章:Normal forms。
如果您有一个好的设计,但仍然需要优化性能,请尝试Denormalisation。
如果您有关系模型无法有效涵盖的特定需求,请查看NoSQL一词涵盖的其他模型。
一些查询/模式优化:
使用 DISTINCT 或 GROUP BY 时要小心。我发现许多新开发人员会在真正不需要的地方使用 DISTINCT,或者可以使用 Exists 语句或派生查询更有效地重写它。
注意左连接。我经常发现新的 SQL 开发人员会忽略现有的模式,并在真正不需要的地方使用左连接。例如:
Select
From Orders
Left Join Customers
On Customers.Id = Orders.CustomerId
如果 Orders.CustomerId 是必填列,则不必使用左连接。
成为新功能的学生。目前,MySQL 不支持公用表表达式,这意味着某些类型的查询很麻烦,并且可能比支持 CTE 时更慢。然而,这不会永远是真的。跟上 MySQL 中的新语法特性,这些特性可用于提高现有查询的效率。
您不必在任何地方都使用代理键。可能有更适合智能键的表(例如美国州缩写、货币代码等),这将使开发人员在许多情况下避免额外的连接。
如果可能,找到将数据归档到 OLAP 或报告服务器的方法。生产数据越小,运行速度就越快。
简洁地模拟您的问题的设计始终是一个好的开始。过度概括数据模型会导致性能问题。例如,我听说过一些项目力求超级灵活性,它们将 RDBMS 用作愚蠢的“名称/价值”存储 - 结果的性能令人震惊。
一旦一个好的设计到位,然后使用 RDBMS 提供的工具来帮助它实现良好的性能。单个字段 PK(无复合),但复合业务键作为具有唯一约束的索引,使用适当的数据类型,例如对数值使用适当的数字类型而不是 char 或类似的。还应考虑运行 RDBMS 的硬件的物理属性,因为大部分查询时间通常是磁盘 I/O - 但当然不要认为这是理所当然的 - 使用分析器找出时间的去向.
根据更新/查询比率,物化视图/索引视图可用于提高运行缓慢的查询的性能。穷人的替代方法是使用触发器来调用一个过程,该过程用运行缓慢、不经常更改的视图的结果填充表。
查询优化有点像黑魔法,因为它通常依赖于数据库,但这里给出了一些经验法则 -优化 SQL。
最后,尽管可能超出了您的问题的预期范围,但在您的应用程序中使用良好的数据访问层,并避免自行推出 - 肯定有适用于所有主要语言的测试和高性能实现。在数据访问层、中间层和应用层使用缓存有助于显着提高性能。
尽可能少使用查询。使用“JOIN”,并对您的表进行分组,以便单个查询给出您的结果。
一个很好的例子是Modified Preorder Tree Transversal ( MPTT ),用于在单个查询中获取所有的树节点父节点。
采取整体方法进行优化。
考虑慢速磁盘、网络延迟、内存不足和服务器负载的影响。