Rails MySQL 查询时间混乱

Posted

技术标签:

【中文标题】Rails MySQL 查询时间混乱【英文标题】:Rails MySQL query time confusion 【发布时间】:2010-01-29 11:16:59 【问题描述】:

我有一个计数计算查询,我在我的 Rails 应用程序中运行了数千次,数据库中的每个客户一次。

当我在禁用查询缓存的 mysql 客户端中运行查询时,查询持续时间超过 1 毫秒。

但是,当我在启用查询输出的情况下从 Rails 控制台运行任务时,我注意到在前几个非常快的查询之后,其余查询的时间突然从不到 1 毫秒增加到大约 180 毫秒.

我已经减小了 innodb_buffer_pool_size 以查看行为的变化,但没有注意到任何事情。

这是控制台的输出:

  EmailCampaignReport::Open Columns (143.2ms)   SHOW FIELDS FROM `email_campaign_report_opens`
  SQL (0.3ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332330) 
  SQL (0.2ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 333333) 
  SQL (0.2ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332661) 
  SQL (0.1ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332326) 
  SQL (0.1ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332665) 
  SQL (0.2ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 336027) 
  SQL (0.2ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 333001) 
  SQL (0.2ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 331983) 
  SQL (0.1ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332668) 
  SQL (0.1ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332316) 
  SQL (0.1ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332325) 
  SQL (0.1ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 331995) 
  SQL (0.2ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 334007) 
  SQL (0.2ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 333326) 
  SQL (0.1ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332998) 
  SQL (183.9ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 334673) 
  SQL (183.7ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 336751) 
  SQL (183.6ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 333334) 
  SQL (186.3ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332663) 
  SQL (183.7ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332328) 
  SQL (186.3ms)   SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332659) 

在该表的 customer_id 列上有一个索引。

有人对为什么会发生这种情况有任何建议吗?

谢谢

【问题讨论】:

您可以发布您的表架构以便我们查看索引等吗? 【参考方案1】:

为什么不只运行一个查询?

SELECT customer_id, count(*) AS count_all FROM `email_campaign_report_opens` GROUP BY customer_id;

如果您有太多记录而担心将它们全部退回,那么请分批进行,但我只是不明白您为什么真的要为每个客户运行此查询。

【讨论】:

很高兴为您工作。在 ActiveRecord 中很容易产生使用对象和迭代器做所有事情的心态,但有时最好使用一点 SQL。【参考方案2】:

这是否也发生在您的 rails 应用程序中,还是仅在您在控制台中运行时发生?另外,您是在使用 Aptana 之类的客户端,还是在 shell 中运行它?

【讨论】:

这是在 shell 中运行的,它也确实发生在 Rails 应用程序中。【参考方案3】:

这是什么版本的 Rails? 根据您的版本和您的 Ruby/Rails 代码,您可能会缓存大量数据而不使用它,并且过了一段时间它必须在获取新数据之前进行垃圾收集,这可能解释了延迟。 请注意,这是一个猜测。

【讨论】:

【参考方案4】:

将counter cache 添加到关联是否有意义(阅读:将email_campaign_report_opens_count 添加到您的Customer 模型)?当然,您必须在迁移期间初始化计数器,但它应该非常快,您甚至不需要在遍历客户表时触摸关联的表。

【讨论】:

好建议。这几乎就是我正在做的事情,我在客户模型中有一个类似的计数字段,该脚本正在通过获取所有计数进行更新。在创建关联时更新计数器缓存可能会更好。在初始迁移期间仍然会遇到查询速度问题,但至少是一次。

以上是关于Rails MySQL 查询时间混乱的主要内容,如果未能解决你的问题,请参考以下文章

Rails/MySQL:使用 LEFT JOINS 的 Group/Distinct 使查询时间加倍/性能降低

厌倦了我的 Rails 应用程序的 Heroku SSH 混乱

Mysql 5.7 json 数据类型,在 Rails 5 中使用 activerecord 查询

rails 部分模板中的可选局部变量:我如何摆脱(定义的?foo)混乱?

如何在 Rails 中关闭 MySQL 严格模式

Sequelize 关联和查询此 mysql 查询