我意识到这是一种元编程问题,但我假设这里有足够的有经验的人给出了一个不错的答案。
我刚刚再次构建一个查询,从表中检索一些数据。
SELECT pl.field1, pl.field2
FROM table pl
LEFT JOIN table2 dp on pl.field1 = dp.field1
WHERE dp.field1 IS NULL
执行此查询需要花费很长时间(1800+秒)。
在我厌倦了等待并努力EXPLAIN
查询之后,结果发现全表扫描已经完成。
我在dp.field1上创建了一个索引,之后几乎是查询,创建该索引的时间不到一秒。
从EXPLAIN
来看,这并不难确定。为什么MySQL不能或不会自动执行此操作?花费一秒钟来创建该索引将使查询立即生效,因此MySQL理论上可以创建一个临时索引,使用它来执行查询然后再次删除它,这仍然比替代方案快几个数量级。
我期待通常的答案是“确保你设计一个好的架构”或“mysql只做你告诉它做的事情”,但我想知道是否可能有技术原因这是为什么坏主意。
答案 0 :(得分:2)
对于基数较低的列,使用B树索引不是一个好主意。对于低基数,B树变得退化,与全表扫描相比,实际上增加了查询时间。
因此,始终创建B-Tree索引并不是一个好主意。至少它也必须考虑基数。也许还有其他一些事情。
答案 1 :(得分:1)
非常简单 - 因为这个想法并没有真正使用当前的RDBMS引擎设计。
对于单个用户来说没问题,但是数据库被设计为支持许多并发用户,并且让每个用户的查询也运行推测优化步骤(“我可以通过创建索引来加速此查询吗?”),并创建该用户索引在某些情况下是一种非常昂贵的操作,在任何程度上都会变慢。使索引“单独使用”将浪费计算时间和磁盘空间,但是依次拥有大量永久索引会通过调查给定查询的许多索引来减慢查询优化器的速度。它还会减慢数据修改操作的速度。
不可否认,在现代硬件上,这些问题并不那么重要 - RDBMS引擎的基本设计可以追溯到磁盘空间昂贵,CPU速度慢几个数量级,内存是一种难以想象的奢侈品。
答案 2 :(得分:0)
我只是在为MySQL发言,因为可能有一个数据库系统会自动修改你的数据库设计。
简单的答案是,MySQL只是做你告诉它做的事情。
MySQL无法预测未来。只有你可以。您对数据的了解远远超过MySQL。 MySQL保留了一些统计信息,但是它猜测在实际尝试之前对非常稀疏的信息(有时是过时的)执行查询的最佳方法。一旦它开始执行,它就不会改变它的计划,无论猜测有多么错误。它用于猜测的方法都有很好的记录。我们的工作是提供能够带来最大收益的索引,甚至有时提示它应该使用这些索引。
如果你告诉MySQL执行一个需要进行表扫描的查询,它会假设你知道它会进行表扫描,因为它在文档中告诉你它会。它只是服从。
不允许DBA做出决策的数据库系统不能很好地扩展。总是要做出权衡,你就是制造它们的人。 MySQL是锤子,而不是木匠。