如何让MySQL为视图查询使用索引?简短的回答,提供MySQL可以使用的索引。

在这种情况下,最佳指数可能是“覆盖”指数:

... ON highscores (player, happened_in, score)

它可能是MySQL将使用该索引,EXPLAIN将显示:“使用索引”由于WHERE player = 24(在索引的引导列上的一个等式谓词GROUP BY happens_id(索引中的第二列) ,可以允许MySQL使用索引来优化,以避免排序操作。在索引中包括score列将允许完全从索引满足查询,而不必访问(查找)由索引引用的数据页。

这是快速的答案。更长的答案是MySQL不太可能使用具有用于视图查询的happens_id的前导列的索引。

为什么视图导致性能问题

MySQL视图中的一个问题是MySQL不会将谓词从外部查询“推”到视图查询中。

您的外部查询指定WHERE happens_in = 2006.当它运行内部“视图查询”时,MySQL优化器不考虑谓词。该视图的查询在外部查询之前单独执行。从查询的执行结果集获得“物化”;也就是说,结果存储为中间MyISAM表。 (MySQL称之为“派生表”,当您理解MysQL执行的操作时,它们使用的名称是有意义的。)

底线是,当您定义了在somet_in上定义的索引时,它不会被MySQL用于形成视图定义的查询。

在创建中间“派生表”之后,使用“派生表”作为rowource执行外部查询。这是外部查询运行时评估的是happens_in = 2006谓词。

注意,来自视图查询的所有行都被存储,这在(在你的情况下)是一个为Happ_in的EVERY值的行,而不仅仅是在外部查询中指定一个相等谓词的行。

处理视图查询的方式可能是某些人“意外”的,这是与其他关系数据库处理视图查询的方式相比,在MySQL中使用“视图”可能导致性能问题的一个原因。

使用合适的覆盖索引提高视图查询的性能

给定你的视图定义和查询,你最好得到的将是一个“使用索引”访问方法的视图查询。要做到这一点,你需要一个覆盖指数,例如。

... ON highscores (player, happened_in, score).

这可能是现有视图定义和现有查询的最有利的索引(性能明显)。播放器列是前导列,因为您在视图查询中对该列有一个相等谓词。接下来是happens_in列,因为您对该列有一个GROUP BY操作,MySQL将能够使用此索引来优化GROUP BY操作。我们还包括score列,因为它是查询中引用的唯一的其他列。这使得索引成为“覆盖”索引,因为MySQL可以直接从索引页面满足该查询,而无需访问基础表中的任何页面。这是好的,我们要走出那个查询计划:“使用索引”没有“使用filesort”。

将性能与不使用派生表的独立查询进行比较

您可以将查询的执行计划与视图和等效的独立查询进行比较:

SELECT player
, MAX(score) AS highest_score
, happened_in
FROM highscores
WHERE player = 24
AND happened_in = 2006
GROUP
BY player
, happened_in

独立查询还可以利用覆盖索引,例如

... ON highscores (player, happened_in, score)

但不需要实现中间MyISAM表。

我不确定任何以前提供了直接回答你提出的问题。

问:如何让MySQL使用INDEX进行视图查询?

A:定义视图查询可以使用的合适的INDEX。

简短的答案是提供一个“覆盖索引”(索引包括视图查询中引用的所有列)。该索引中的前导列应该是使用相等谓词引用的列(在您的情况下,列播放器将是一个前导列,因为在查询中有一个player = 24谓词。此外,GROUP BY应该是索引中的引导列,这允许MySQL通过使用索引而不是使用排序操作来优化GROUP BY操作。

这里的关键点是视图查询基本上是一个独立的查询;该查询的结果存储在中间“派生”表(当对视图的查询运行时创建的MyISAM表)。

在MySQL中使用视图不一定是一个“坏主意”,但我强烈警告那些选择在MySQL中使用视图的人应该知道MySQL如何处理引用这些视图的查询。 MySQL处理视图查询的方式与其他数据库(例如Oracle,SQL Server)处理视图查询的方式不同(显着)。