优化很难查询(可能与squeel)

编程入门 行业动态 更新时间:2024-10-17 13:39:09
本文介绍了优化很难查询(可能与squeel)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

有这样code(使用PublicActivity宝石和放大器; Squeel)

高清指数     @activities = Activity.limit(20).order {created_at.desc}     @One = @ activities.where {trackable_type =='邮'}包括(可跟踪:[:作者:项目])     。@two = @ activities.where {trackable_type =='项目'}包括可跟踪:[:所有者]     @activities = @One + @two   结束

不过,它创建 8 SQL请求:

选择活动。* FROM活动WHERE活动。trackable_type=邮报ORDER BY活动。created_atDESC LIMIT 20       选择上岗。* FROM上岗WHERE上岗。IDIN(800,799,798,797,796,795,794,793,792,791,790,789,788,787,786, 785,784,783,782,781)       选择用户。*从用户WHERE用户,IDIN(880,879,878,877,876,875,874,873,872,871,869,868,867,866,865, 864,863,862,861,860)       选择项目。*从项目WHERE项目,IDIN(80,79)       选择活动。* FROM活动WHERE活动。trackable_type=项目ORDER BY活动。created_atDESC LIMIT 20       选择项目。* FROM项目WHERE项目,IDIN(80,79,78,77,76,75,74,73,72,71,70,69,68,67,66, 65,64,63,62,61)      选择用户。*从用户WHERE用户,IDIN(870,859,848,837,826,815,804,793,782,771,760,749,738,727,716, 705,694,683,672,661)

  • activites要求未加入
  • 在一些用户(后业主和项目业主)将被加载两次
  • 在一些项目被载入两次
  • @activities是数组。导轨关系合并方法(除了 + )不与code以上的工作。
  • 任何想法,以优化呢?

    解决方案

    在简单地说,你不能进一步优化任何不使用SQL。这是Rails的业务的方式。它不允许访问加入其中该查询所构成的AR模型外域。因此,为了得到其他的表中的值,它在每一个查询。

    也不允许 UNION 或花哨的,其中提供解决问题的其他方面的条件。

    好消息是,这些查询都是有效率的(因为trackable_type有标号)。如果结果的大小是任何实质性(比如几十行),在I / O时间将主导7个简单的查询副轻微的额外开销1复杂。

    即使使用SQL,这将是很难得到你想要在一个查询所有连接的结果。 (这是可以做到的,但结果将是一个哈希值,而不是一个AR实例。所以依赖code将是丑陋的。)一查询,每个表是有线pretty的深入到活动记录。

    @ Mr.Yoshi的解决方案是一个很好的妥协使用最小SQL但它不会让你有选择地加载任何作者或项目 + 所有者根据 trackable_type 字段。

    修改

    以上是正确的Rails的3.轨道4为@CMW说,在 eager_load 方法做同样的包括使用外部连接,而不是单独的查询。这就是为什么我喜欢这样!我总是学到一些东西。

    There is such code(using PublicActivity gem & Squeel)

    def index @activities = Activity.limit(20).order { created_at.desc } @one = @activities.where{trackable_type == 'Post'}.includes(trackable: [:author, :project]) @two = @activities.where{trackable_type == 'Project'}.includes trackable: [:owner] @activities = @one + @two end

    But it creates 8 SQL requests:

    SELECT "activities".* FROM "activities" WHERE "activities"."trackable_type" = 'Post' ORDER BY "activities"."created_at" DESC LIMIT 20 SELECT "posts".* FROM "posts" WHERE "posts"."id" IN (800, 799, 798, 797, 796, 795, 794, 793, 792, 791, 790, 789, 788, 787, 786, 785, 784, 783, 782, 781) SELECT "users".* FROM "users" WHERE "users"."id" IN (880, 879, 878, 877, 876, 875, 874, 873, 872, 871, 869, 868, 867, 866, 865, 864, 863, 862, 861, 860) SELECT "projects".* FROM "projects" WHERE "projects"."id" IN (80, 79) SELECT "activities".* FROM "activities" WHERE "activities"."trackable_type" = 'Project' ORDER BY "activities"."created_at" DESC LIMIT 20 SELECT "projects".* FROM "projects" WHERE "projects"."id" IN (80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61) SELECT "users".* FROM "users" WHERE "users"."id" IN (870, 859, 848, 837, 826, 815, 804, 793, 782, 771, 760, 749, 738, 727, 716, 705, 694, 683, 672, 661)

  • activites request are not joined
  • some users (post owner and project owner) are loaded twice
  • some projects are loaded twice
  • @activities is Array. Rails relations merge methods(except +) don't work with the code above.
  • Any ideas to optimize it?

    解决方案

    In a nutshell, you can't optimize any further without using SQL. This is the way Rails does business. It doesn't allow access to join fields outside the AR model where the query is posed. Therefore to get values in other tables, it does a query on each one.

    It also doesn't allow UNION or fancy WHERE conditions that provide other ways of solving the problem.

    The good news is that these queries are all efficient ones (given that trackable_type is indexed). If the size of the results is anything substantial (say a few dozen rows), the i/o time will dominate the slight additional overhead of 7 simple queries vice 1 complex one.

    Even using SQL, it will be difficult to get all the join results you want in one query. (It can be done, but the result will be a hash rather than an AR instance. So dependent code will be ugly.) The one-query-per-table is wired pretty deeply into Active Record.

    @Mr.Yoshi's solution is a good compromise using minimal SQL except it doesn't let you selectively load either author or project+owner based on the trackable_type field.

    Edit

    The above is all correct for Rails 3. For Rails 4 as @CMW says, the eager_load method will do the same as includes using an outer join instead of separate queries. This is why I love SO! I always learn something.

    更多推荐

    优化很难查询(可能与squeel)

    本文发布于:2023-10-23 05:33:16,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1519938.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:很难   能与   squeel

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!