我有一个名为传感器注册表的模型的Rails 5应用程序。
目前有大约160,000条记录,但在尝试显示此数据时,我的加载时间极短。
该应用程序运行在双核Intel(R)Xeon(R)CPU E5-2670 v3 @ 2.30GHz和2GB RAM上。
服务器日志显示以下内容:
开始GET" / sensor_registries" 2017-01-10 23:43:41 +0000
的187.220.30.180无法从187.220.30.180渲染控制台!允许的网络:127.0.0.1,:: 1,127.0.0.0/127.255.255.255
ActiveRecord :: SchemaMigration Load(1.2ms)SELECT" schema_migrations"。* FROM" schema_migrations"
SensorRegistriesController #index处理为HTML 在layouts / application
中渲染sensor_registries / index.html.erbSensorRegistry加载(604.0ms)SELECT" sensor_registries"。* FROM" sensor_registries"
传感器负载(0.6ms)SELECT"传感器"。* FROM"传感器"在哪里"传感器"。" id" IN(49,50,51,52,53,54,55,56,57,58,59,60,65,61,63,64,62)
在布局/应用程序中呈现sensor_registries / index.html.erb(54663.9ms) 在55468ms完成200 OK(浏览次数:54827.7ms | ActiveRecord:611.5ms)
我摆脱了N + 1问题,但我想知道是否还有更多关于数据库查询的事情。
无论如何,问题似乎是在渲染页面时,处理它需要大约54秒。
有没有办法优化CPU使用率?
加快流程并以足够快的速度向用户显示数据的最佳解决方案是什么?
答案 0 :(得分:5)
这当然不是硬件问题,而是实现问题。如果不了解更多有关您的数据结构和架构的信息,这是不可能完美回答的,但有一些想法可以帮助您追踪问题:
1)渲染页面有多大?数据的庞大规模是否会导致渲染时间变慢?如果这是问题并且渲染的页面太大,请考虑对结果进行分页。
2)ruby进程在任何时候使用了多少内存?当你说,它"有大约160,000条记录"时,我假设您正在谈论sensor_registries表,我假设随后的传感器查询sensors.id in (...)
位是用一些数据构建的来自sensor_registries表。如果在完成任何进一步的工作之前将整个表加载到内存中,那么ruby进程是否可能只是内存不足?
3)另外,整个表是否真的需要一次性加载?您可能需要查看http://apidock.com/rails/ActiveRecord/Batches/find_in_batches。该方法非常适合分解需要在大型表上完成的工作。
4)甚至更好 - 而且实际上并不是更好的方式来重新思考你的架构。将内存中的整个表作为同步请求(即使是小型请求)的一部分加载几乎总是禁止的。你能想出一个SQL查询来获取你需要的所有记录而不加载整个表吗?
5)如果你绝对需要整个表,那么在一次加载后缓存结果呢?如果您希望查询结果在具有相同参数的请求之间相同,您是否可以使用params构造缓存键,并使用它来存储结果?至少就这样,第一个之后的所有请求都会很快(呃)。
答案 1 :(得分:2)
用户遵循以下方法:
答案 2 :(得分:1)
使用分页或其他内容(最多5-10)减少您同时显示的记录数量。这样,您的查询和渲染将会大量减少。我更喜欢will_paginate gem,但还有更多。
在视图中,减少用于渲染每个传感器的逻辑量,并为单个传感器创建单独的视图(显示)。在单传感器视图中,您可以添加更多逻辑。
使用新的Relic gem来监控您的应用,并查看哪个请求需要花费大量时间。也许你有很慢的外部资源,如api调用等,你可以通过Ajax执行,而不是在服务器上执行:https://docs.newrelic.com/docs/agents/ruby-agent/installation-configuration/ruby-agent-installation
这些是基础知识,一旦完成,继续进行急切加载和缓存。
对于急切加载,请阅读:http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations
有关缓存,请阅读DHH的博文:https://signalvnoise.com/posts/3113-how-key-based-cache-expiration-works