【问题标题】:Query taking very long the first time it runs查询第一次运行需要很长时间
【发布时间】:2013-08-21 16:34:55
【问题描述】:

我的网站在访问高峰期出现严重问题。经过多次故障排除后,我发现问题出在数据库上。

我有这个在 Index 上运行的主要查询,它检索数据表。

在繁忙的一天,网站第一次加载需要 30 到 45 秒,但之后每次加载都非常快,大约 5 分钟后再次变慢,最终网站因负载过多而崩溃.

我直接在数据库上测试了查询,结果完全一样。

这更多地与查询或 MySQL 配置有关吗?

它在返回结果很小的情况下工作得非常好,但是在繁忙的一天,当列表非常大时,它真的会变慢并杀死网站。

编辑:

感谢您的所有建议。

我稍微修改了查询并对数据库进行了一些修改,因为有些名称不合理。

根据您的所有建议,我还修改了查询以删除通配符搜索以及对不再需要的表的一些冗余请求。

这是查询本身:

SELECT g.id, g.`name`, g.scores, g.sportFK, g.`desc`, g.`date`, s.id AS streamid
       FROM games AS g
       LEFT JOIN streams AS s ON s.gameFK = g.id
             WHERE
                  (g.date >= '" . $date . "' AND g.date <= '" . $newdate . "') 
                  AND g.sportFK IN (" .  $sportfk . ") 
                  ORDER BY g.date ASC"

经过测试,查询的第一次性能仍然在 33s 运行,随后的每次执行都在 0.04s 运行,这表明高峰时间来时对站点的影响是一样的。

我还准备了来自EXPLAIN的请求信息。

这是用于“游戏”表的

GAMES TABLE:

SIZE: 6MB
ROWS: 14841
TYPE: INNODB

这是用于“STREAMS”表的

STREAMS TABLE:

SIZE: 80MB
ROWS: 135296
TYPE: MyISAM

编辑:马丁感谢您对写作提出意见。该数据库确实以相当固定的时间间隔从另一个来源填充,因此将不断发生 READ 和 WRITE 操作。我将不得不对此进行更多研究。

【问题讨论】:

  • 您的表上有正确的索引吗?您不需要不从表中获取所有 (*) 数据吗?
  • 当参数不是模式时,为什么要使用LIKEprod_namecat_name 可以包含通配符吗?
  • 此查询的可能瓶颈是“LIKE”、“JOIN”和子“SELECT” - 如果可能,尽量避免它们
  • 你也应该给我们解释的输出。
  • 您需要向我们展示表和索引定义,以及每个表的行数。也许您的表格定义不佳。也许索引没有正确创建。也许您认为您在该列上没有索引。没有看到表和索引定义,我们无法判断。我们还需要行计数,因为这会极大地影响查询优化。如果您知道如何处理EXPLAIN 或获取执行计划,请将结果也放入问题中。

标签: mysql sql database performance


【解决方案1】:

可能发生的情况是,第一次运行查询的额外时间用于编译查询和制定执行计划。这会保持缓存一段时间,然后再次发生。

解决方案是将您的查询放入存储过程中。

【讨论】:

  • 谢谢,我肯定会考虑使用存储过程,因为我没有任何使用经验,所以我必须阅读一下它。
【解决方案2】:

好吧,这个查询对于每个 DB 开发人员来说都是性能上的恐惧 :-)

第一次时间会因为查询编译和执行计划计算而延长。你可以使用EXPLAIN查看它。

由于该行为在 5 分钟内重复,我会说索引本身或缺少索引应该有问题。

您应该指定网站负载中是否只有 read 或并发读取(使用您的查询)以及 writes

索引重新计算会在您还执行写操作时发挥作用。另一个可能的问题是锁定。假设每 5 分钟有人写入数据,查询非常复杂,因此它应该锁定表以进行写入事务,而您的读取将等到提交/回滚。

请注意,此查询非常复杂,而且永远不会很快 - 我的意思是非常快。

  • 另一个表使用索引计数
  • 一个连接到另一个条件较大的表 - 连接本身很慢
  • 两个 where 子句 => 两个索引
  • 使用另一个索引排序

您会看到有几个索引。写操作只是锁定表和索引并更新它们,你有 5 个。内数也不好。

如果您需要非常好的性能或定义经典方法,我会推荐更好的数据库或域设计:经常读写?而不是重新设计。

【讨论】:

  • Martin 感谢您对本文提出的观点。该数据库确实以相当固定的时间间隔从另一个来源填充,因此将不断发生 READ 和 WRITE 操作。我将不得不对此做更多的研究。您认为目前的状态是否有所改进?
  • 我们在表锁定方面遇到了很多麻烦,导致我们克隆表。我的意思是我们已经采用了用例并定义了哪些操作会阻塞另一个操作并将数据分成单独的表。现在当一个线程/客户端写入数据时,第二个根本不受影响。当我准确地说,我们的案例如下:我们得到了某种主要的聚合。它可以使用 REST 部署到服务器,服务器可以处理它。我们在这些主要聚合的级别上划分表,因此当有人部署一个聚合时,它不会阻止服务器端对另一个聚合的处理,因为它们是不同的
  • 表格。我们学到了很多关于数据库的知识。它鼓励我开始阅读 NoSQL。原因是 RDBMS,在我们的例子中是 MS SQL,会做很多意想不到的事情或难以学习或判断的事情。例如。它有时会锁定整个表而不是索引本身,有时即使表包含正确的定义也不使用索引,因为它只是决定不使用它。或者像clustered index 这样的术语是漫长的冬夜的话题。很多事情在 RDBMS 中都能发挥神奇的作用。
【解决方案3】:

如果一个查询被多次执行,数据库在后台进行缓存以提高性能是很正常的。 如果您想提高性能,您可能需要制定解释计划并改进您的数据库结构或改进您的查询结构。

为了改进数据库,检查解释计划并确保没有像全文扫描这样的昂贵操作。 例如,您可能希望看到在 g.name 和连接列上添加索引的影响。 尝试添加索引,看看成本改进。 在缓慢写入时添加索引并增加数据库大小时要小心。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 2011-01-17
    • 2019-04-21
    • 2022-08-20
    • 1970-01-01
    • 2019-04-15
    相关资源
    最近更新 更多