0

假设我有两个这样的表:

雇主(id、name、....、deptId)。
部门(id,部门名称,...)。

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

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

尽可能快。

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

  • 非规范化表:

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

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

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

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

4

4 回答 4

5

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

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

于 2009-01-09T14:32:29.220 回答
1

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

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

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

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

于 2009-01-09T14:42:41.943 回答
1

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

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

你需要做的是:

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

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

于 2009-01-09T15:03:02.713 回答
0

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

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

但是视图也会对将来维护代码的开发人员“隐藏”一些东西,让他们想象查询没有实际复杂。

于 2009-01-10T08:07:22.880 回答