【问题标题】:MySql slow data fetching [closed]MySql缓慢的数据获取[关闭]
【发布时间】:2012-10-12 01:34:22
【问题描述】:

我有一个包含大量行的 MySql 表。我正在做一个简单的请求,它工作得非常快。当请求本身只需要 0.3 秒时,向客户端获取数据的唯一问题是大约 150 秒的速度非常慢。

我在客户端和 Amazon EC2 MySql 实例上使用 php 5.3 + ZendFramework。 PHP 代码和 MySql 位于不同的服务器上。

谁能告诉我如何提高数据获取速度?

【问题讨论】:

  • 你能提供你正在运行的表结构和查询吗?需要检查你有什么索引等。如果它们都是有序的,那么我会看看分区策略。
  • 这里需要更多信息!您的查询、其执行计划和配置文件、(相关)数据库架构、服务器配置、网络设计、硬件规格......
  • 我认为您通过 amazon ec2 和您的服务器达到了连接速度限制。此外,您的服务器和计算机的连接速度也很慢
  • 什么是巨大的?你能定义巨大吗?以及您的查询是如何解决的。您是否为您的数据库编制了索引,您是否正确地查询了所有数据?无线检索数据和通过电缆检索数据也有区别,因此您在这里放弃的信息并没有太多工作要做。
  • 据我了解,您的问题暗示有些事情比它应该的要慢。所以这不是关于如何减少数据量,而是在给定的数据量下获得预期的速度。在这种情况下,您可能想在serverfault.com 上问这个问题,有能力的管理员(很可能比我们单纯的开发人员更好)可以告诉您如何识别作为瓶颈的确切组件,并且 - 如果它真的是传输 - 甚至可能如何要解决这个问题。 (但答案可能与此处相同:传输 x*10GB MySQL->PHP 时您期望什么 ;-))

标签: php mysql amazon-ec2 high-load


【解决方案1】:

根据您最终提供的正在运行的查询的 cmets。

select * from table

您还说您有“大量的行”。这应该足够简单,您可以理解为什么需要永远传输到查询您的数据库的盒子。

而且,仅仅因为您的查询运行速度很快,您仍然需要处理网络限制。另外,假设您实际收到结果后,假设您使用的是 ORM,您会发现结果集的水合会增加您的请求的复杂性和时间。

总的来说,您自己回答了这个问题。不要在表格“巨大”的情况下使用select * from table

您应该考虑在查询中添加limits 和偏移量,并且只选择您实际需要的行。

此外,“巨大”是非常主观的。对我来说,一张大表大约有 1000 万行。但对于其他人来说,1000 万是非常小的。我什至不想在一张巨大的桌子上加上一个数字。

【讨论】:

  • 我同意,我实际上是在尝试编辑我的一个 cmets。如果你说你的桌子很大,那么select * from table 简直就是愚蠢。我不知道你眼中巨大的定义......
  • (另外,作为建议评论,您应该在原始问题中提供尽可能多的信息。上面 cmets 中的迭代应该足以表明您没有提供所需的一半我们需要回答的信息)。
  • 没有其他信息,一切都很简单。只是一个有 6 列 50 000 条记录的表。还有一个查询:“select * from table_name”。而已。主要的麻烦是将所有这些记录发送给客户。我想找到一种方法来加快 mysql 服务器和客户端之间的数据传输。由于我无法提高网络连接速度,我想找到一种方法来压缩查询结果数据以更快地传输它。我需要从表中选择每一行以将它们放入 csv 文件中。所以我不认为我可以使用这个限制。
【解决方案2】:

缓慢是因为您从表中检索所有数据,并且由于您的数据库和网站有两台不同的服务器,所有需要通过网络传输的数据都会带来额外的缓慢。

如果你问为什么在你的客户端运行会更快,那是因为大部分的sql客户端会自动增加行数限制。

【讨论】:

    【解决方案3】:

    正如所有 cmets 所说:您必须提供更多信息才能获得准确(或至少不那么模糊)的答案。但是对于您编写的每个查询,您应该牢记一些经验法则:

    • 尽可能避免使用SELECT *,尤其是SELECT COUNT(*) 之类的内容,只选择您感兴趣的那些字段。
    • 将数据拆分到巧妙索引的表中并使用JOIN。一个好的JOIN 可以提高性能,通常非常显着。
    • 使用EXPLAIN EXTENDED,避免MySQL必须在磁盘上创建临时表的情况
    • 使用EXPLAIN 时,还要检查隐式CASTCOLLATION 转换。与 PHP 不同,UNSIGNED INTEGERVARCHAR 不同。将其视为$x = 123; 后跟if ($x === '123'),这将是错误的:字符串!== 整数...
    • 避免使用大型数据字段(如 MEDIUMTEXT),因为它们总是会导致磁盘访问
    • 尽可能避免使用LIKE,尤其是在使用通配符时 (x LIKE 'y%z')
    • 记住:% 不是唯一的通配符:_ 是单个字符的joker
    • 你有一个索引,但你能用更多的索引来做,而不会变得愚蠢吗?不要索引太少,也不要索引太多
    • 您是否选择了正确的存储引擎
    • EXPLAINEXPLAINEXPLAIN 再次...
    • 如果您使用慢查询,缓存结果
    • LIMIT-ing "huge" 数据集的结果是必须的。如果您要获取 大量 块数据,您将如何处理它们?我无法想象所有数据将作为一个大块发送给客户端的情况,是吗?

    【讨论】:

    • 你为什么要避开SELECT COUNT(*)
    • @VolkerK:这是一个很好的经验法则,因为COUNT(*) 在不同的引擎上表现不同。虽然它在 MyISAM 表上几乎没有区别,但 COUNT(*) 在 InnoDB 上相对昂贵。无论您使用什么引擎,使用SELECT(some_index_field) 都会表现得更加可预测
    • 另外,不推荐使用 SELECT *,因为您可以从查询中实际推断出缺乏详细程度和洞察力。你不知道它实际返回的是什么。一些开发人员可能会出现并更改架构并导致您的查询出现并发症/问题。
    猜你喜欢
    • 2018-10-30
    • 2023-02-16
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多