慢SQL查询的特征

Ger*_*Ger 3 mysql sql database query-performance

最近在一次采访中被问到为什么SELECT对MySQL数据库的查询会非常缓慢,并提出以下建议:

  1. JOIN在选择上执行多个
  2. 关键过滤器字段中缺少索引(索引?)

还问了解决问题的方法,我说:

  1. 如果查询具有高度重要性,则会对您的数据进行非规范化(我知道这会导致数据重复但是还有另一种方法可以避免 JOINs吗?)
  2. 将索引添加到筛选列.

是否存在SQL查询效率低下的其他特征?请注意,我纯粹在寻找有关如何加速查询的提示,因此假设数据库服务器是完美的:-)

Chr*_*s J 8

查询可能很慢的原因有几个.无论如何,要真正了解查询规划器正在做什么,您应该运行explain它.explain大多数DBMS上的命令将告诉您查询计划程序将使用哪些索引,可以获得多少行数据,以及在开始获取结果之前需要处理多少行数据.

现在,为了给出查询可能运行缓慢的一些具体原因,您对索引是正确的.缺少索引将导致对查询中的表进行顺序扫描,如果这些表很大,可能会使事情变慢.在您正在加入或在where子句中使用的列上创建索引肯定有帮助.但有时候,查询规划器做得很差,你需要帮助它使用'force'命令来指示它应该使用哪个索引.

加入会减慢事情的速度,这是一种误解.单级连接通常很好.例如,您正在从表A中选择数据,并且您将B连接到A,将C连接到A.表B和C的连接是一个级别连接.多级联接需要更多时间来处理.这就是为什么在数据仓库和数据集市中,人们喜欢使用星型方案; 这是一个包含度量的单个大表,一个事实表,该查询正在进行,还有其他表与描述性数据,维度表,它们加入了它.星型模式避免多级联接,因此可以快速执行报告查询.

然而,对你的桌子进行非规范化是很诱人的,我强烈建议不要这样做.当你开始对数据库进行非规范化时,如果你存储的数据量越来越大,那么你将会遇到一些严重的问题.同样,维护非规范化表格需要您的工程师对模式有一个非常好的工作知识,这使得技术债务变得更加困难.当然这是一个短期的收获,但长期的痛苦意味着你必须有一个非常好的理由想要这样做.做一些需要扩展的多年项目,你会真正看到非规范化的痛苦.

现在,根据您的需求,通常需要使用生产数据库中的数据构建和更新分离报告数据库,数据集市或数据仓库.这使您可以更自由地设计真正支持您要运行的报告查询的模式,并阻止您攻击生产数据库.

如果缺少资源,则单独数据库的一个不错的替代方法是临时表.临时表是在数据库连接/会话的生命周期中存在的表.其他连接/会话无法查看或访问它,隔离质量,您可以使用它们来存储和索引要在更大更复杂的查询中使用的数据.如果您通过控制台与数据库交互,则非常简单易用.如果您以编程方式使用其中一个并拥有连接池,我认为您可能必须在完成后删除该表; 不能记得,但清理从来都不是坏事.

查询速度慢的一个明显原因是您正在选择大量数据.如果您尝试交叉连接多个表,每个表都有几亿行字符(1000)字段,您的DBMS可能会开始挖掘虚拟内存以执行连接.即使使用索引,也可能导致交换磁盘,一旦开始发生,欢迎来到slowville.

选择subselect(select a, b, (select c, d from e where e.id = a) from f)或在where子句中使用subselect 也可能非常慢,因为subselect实际上是为每行数据执行的查询.在连接中使用子选择不会受到该问题的影响,但是,您实际上是在没有索引的情况下加入临时表,并且根据您使用该子选择检索的数据量,这可能会减慢速度.

in如果您的集非常大,该命令也可能有问题.同样,大型集合基本上是一个没有索引的大型临时表,因此每次检查特定值是否在您的集合中时,您都在执行顺序扫描.

这些是我现在能想到的最突出的原因.还有其他但我认为这将超出堆栈溢出响应的范围;-)