问:Rails数据库调用的最佳实践

时间:2017-07-06 15:32:19

标签: ruby-on-rails postgresql

快速提问。我正在为一位艺术家建立一个投资组合应用程序,目前有9个不同类型的项目表(展览,新闻,新闻,文本,摄影等)。作为视觉艺术家,他希望他的网站能够代表他的愿景。

背景

编辑:信息最初是从控制器加载的,而不是从API调用加载的。之后我将其更改为API调用,因为我担心来自控制器的9次调用太多了。

这意味着该网站的图形和信息都很重。加载所有仅用于导航的信息是15 MB(这是在需要时缩小图像并通过tinypng运行它们之后)。我将所有信息都放到不同的布局视图中,只有在需要保持加载时间并将其抵消时才会呈现,这有助于加速一切。但是这种设置无论哪种方式导致每个页面加载9个不同的数据库调用。

我将后端重建为API端点,因此只在需要时才从数据库中提取信息。这略微增加了信息的加载时间,但是如果那样的话,只会增加一秒钟。我并不为此烦恼,但艺术家可能会这样。

实际问题

所以我一直想知道过去几天,一次是9个数据库调用太多了,它会如何影响可扩展性? Postgres数据库供参考。正常负载,我无法想象有太多用户会在任何给定时间查看该网站,所以我不会担心它。但是当他有一个展览并且有100-500人同时使用该网站时,每个页面加载900-4500个数据库。或者使用API​​路线,人们在找到他们想要的东西之前可能只会进行1或2次呼叫。我只想按照行业最佳实践来处理这种情况,这似乎是提出这个问题的好时机。

此外,这将在heroku当前托管,并想知道哪种方式(一次性或API路由)将更好地处理postgres连接,因为免费套餐(这将是足够的95%的时间)有一个限制20个连接。虽然有几个月他有一个节目我们可以将它提升到下一层60连接。

3 个答案:

答案 0 :(得分:0)

您所描述的内容并非听起来像一个动态网站。除非它有管理部分来修改内容,否则没有理由将数据保存在数据库中或使用网络"应用程序"像Rails。

我建议使用Ruby静态站点生成器。 Jekyll是最受欢迎的,但我建议使用Middleman,因为它可以很容易地从Rails视图模板和帮助程序进行迁移。

如果你真的想使用Rails,那么你的是一个用于视图缓存的教科书用例。如果内容是静态的,则没有理由在每个页面视图中反复加载它。

此外,每页查看9个数据库查询并不意味着什么。它可能很少或者可能很多,它实际上取决于查询。

答案 1 :(得分:0)

查看有关Rails Database Best Practices的博客文章。

如果不了解您的应用程序,请查看是否可以减少使用范围和/或查询对象的数据库调用次数。将呼叫与.includes().join()组合在一起也是减少负载的一种方法。查看数据是否可以与.group().having()汇总。如果每次调用都是必要的,那么您可以通过引入一些索引来提高查询的速度。

根据我的经验,我不会说网页加载应该具有的最大数据库调用数量是行业标准;它实际上取决于返回的数据。

答案 2 :(得分:0)

我不是专家,但我一直处理很多有关优化的问题,我会提出一些自己的建议:

  • 通过CDN提供所有静态资产 - 除非你真的知道你正在做什么让CDN处理缓存

  • 你提到它有一个内置的CMS - 版本所有图像上传到不同的大小,所以你可以通过版本控制优化显示(拇指拇指,中型(最大宽度1920< - > 3840)为其他一切,只有保存/使用大于那些尺寸,如果真的需要)

  • 了解JPG压缩 - 您可以将其从通常的100%降低到70%左右(这取决于实际图像)而不会丢失任何有意义的信息 - 这与非轨道相关,应该按步骤完成关于优化所有图像内容

  • 为了优化通过CMS添加的图像,您可以使用RMagick或Minimagick。在RMagick中,您可以在处理图像时访问self.quality - 除非图像的透明度始终转换为JPG&质量低至70-80%

  • 将查询缓存到数据库本身 - heroku caching

我个人使用一种技术仅在html渲染后加载图像

function loadPortfolios() {
  var collections = $(".profile_collection");
  var imageObj = new Image();
  var image;
  $.each(collections, function () {
    image = $(this).data('source');
    imageObj.src = image;
    $(this).css({ backgroundImage: 'url('+image+')', backgroundRepeat: 'no-repeat', backgroundSize: "cover", backgroundPosition: 'center' });
  });
  $.each($('.image_portfolio, .hover_image'), function() {
    imageObj.src=$(this).data('url');
  });
}

这可以通过在" portfolio"的类型中使用数据属性来实现。因此,一旦加载网站并准备好JS,就会调用此函数。实例化JS Image对象(new Image()),然后将url归因于.src属性,使其开始加载图像。我还没有对它进行基准测试,但很快就会 - 不确定它真的起作用但是如果你尝试它让我知道。我这样使用它的原因是因为对于我来说,减少外部元素的请求数量对于加载JS来说更重要,这样网站才能最快地运行。然后开始获取图像。

我确信还有很多可以做的其他优化措施。 编辑:

如果您也陷入了数据库查询的困境,请查看您在控制器和视图中使用的辅助方法的数量(当您加载很多东西时,它可以真正渲染事情变慢了)。然后看看你如何查询事物。一些例子可能有所帮助。