假设我有两个这样的表:

Employers (id, name, .... , deptId).
Depts(id, deptName, ...).

但是这些数据不会经常修改,我想要这样的查询

SELECT name, deptName FROM Employers, Depts 
    WHERE deptId = Depts.id AND Employers.id="ID"

尽可能快。

我想到了两种可能的解决方案:

  • 对表进行非规范化:

    尽管使用这个解决方案,我将失去“标准化数据库”的一些巨大优势,但这里的性能是必须的。

  • 为非规范化数据创建一个视图。

    我将保持数据标准化并且(这是我的问题),对该视图的查询性能将比没有该视图时更快。

或者用另一种方式提出同样的问题,每次对视图进行查询时,视图都会被“解释”,或者 DBA 中的视图内容如何工作?

有帮助吗?

解决方案

通常,除非您“具体化”视图(这是某些软件(如 MS SQL Server)中的一个选项),否则视图只是转换为针对基表的查询,因此不会比原始视图更快或更慢(减去极少量的数据)翻译查询所花费的时间,与实际执行查询相比根本不算什么)。

你怎么知道你有性能问题?您是否在负载下对其进行分析?你验证过性能瓶颈是这两个表吗?一般来说,在获得硬数据之前,不要假设您知道性能问题从何而来,也不要花任何时间进行优化,直到您知道正在优化正确的内容 - 80% 的性能问题来自 20代码的%。

其他提示

如果 Depts.ID 是该表的主键,并且您对 Employers.DeptID 字段建立索引,那么即使在数百万条记录上,此查询也应该保持非常快的速度。

在这种情况下,非规范化对我来说没有意义。

一般来说,视图的性能与运行查询本身时的性能几乎完全相同。视图的优点是简单地抽象出该查询,因此您不必考虑它。

您可以使用物化视图(或某些人所说的“快照”),但是您的数据只会是上次刷新时的最新数据。

在对其中一个回复的评论中,问题的作者解释说,他正在寻找一种在 MySQL 中创建物化视图的方法。

MySQL 不像其他 DBMS 那样将物化视图的概念包装在一个很好的包中,但它确实拥有创建物化视图所需的所有工具。

你需要做的是这样的:

  1. 创建查询结果的初始具体化。
  2. 在插入雇主表时创建一个触发器,将与新插入的雇主匹配的所有行插入到具体化表中。
  3. 在雇主表中创建删除触发器,从物化表中删除相应的行。
  4. 在雇主表中创建更新触发器,以更新具体化表中的相应行。
  5. 部门表也是如此。

如果您的基础表不经常更新,这可能会起作用;但一旦执行此操作,您需要注意创建/更新/删除操作的额外成本。此外,您还需要确保一些不知道您的诡计的 DBA 在时机到来时不会在没有迁移触发器的情况下迁移数据库。所以要好好记录一下。

听起来像是过早的优化,除非您知道这是一个明确且当前的问题。

MySQL 不会具体化视图,它们并不比针对基表的查询快。此外,在某些情况下,它们会变慢,因为它们优化得不太好。

但是视图也会向将来维护代码的开发人员“隐藏”一些东西,使他们认为查询并不像实际那样复杂。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top