{"action":"opened","issue":{"url":"https://api.github.com/repos/rails/rails/issues/21178","labels_url":"https://api.github.com/repos/rails/rails/issues/21178/labels{/name}","comments_url":"https://api.github.com/repos/rails/rails/issues/21178/comments","events_url":"https://api.github.com/repos/rails/rails/issues/21178/events","html_url":"https://github.com/rails/rails/issues/21178","id":99913897,"number":21178,"title":"Improve includes() prefetches - add debug hints, explore automation","user":{"login":"eiked","id":2196134,"avatar_url":"https://avatars.githubusercontent.com/u/2196134?v=3","gravatar_id":"","url":"https://api.github.com/users/eiked","html_url":"https://github.com/eiked","followers_url":"https://api.github.com/users/eiked/followers","following_url":"https://api.github.com/users/eiked/following{/other_user}","gists_url":"https://api.github.com/users/eiked/gists{/gist_id}","starred_url":"https://api.github.com/users/eiked/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eiked/subscriptions","organizations_url":"https://api.github.com/users/eiked/orgs","repos_url":"https://api.github.com/users/eiked/repos","events_url":"https://api.github.com/users/eiked/events{/privacy}","received_events_url":"https://api.github.com/users/eiked/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-08-09T17:03:22Z","updated_at":"2015-08-09T17:03:22Z","closed_at":null,"body":"When working with queries across multiple tables,\r\nor when rendering datasets resulting from multiple tables,\r\nit is very important to get the includes() right, to avoid the n+1 fetch problem.\r\n\r\nFinding the missing includes() clauses however is not always easy.\r\n\r\nI believe it could be possible to add some code to rails/ActiveRecord\r\nto detect queries that would benefit from includes()\r\n\r\nI believe this could help in 2 situations:\r\n- detecting the query where a includes() clause is missing\r\n- hinting the developer, where a includes() clause may be beneficial\r\n\r\nSuch a tool should be available in developer mode, and it should be possible to disable it ...\r\n\r\nI've not yet gone deep into the details how this could be achieved.\r\nBut let me sketch a first idea:\r\n\r\nA common case is accessing m:n relations:\r\nA->B->C\r\n\r\nUsually B is fetched on first access, and trouble starts when accessing C, one by one\r\n(we want to includes(B: :C) here)\r\n\r\nMaybe we could mark B as 'not prefetched, yet'\r\nand on the second access to C (aka B->C[1])\r\nlog a debug hint, that prefetching A.includes(B: :C) might be a good idea.\r\n\r\nI believe could add a reference to the code line where A (or A->B or even A->B->C.first) was triggered.\r\n\r\nSuch a mechanism should be request scoped,\r\nso that it works for the lifetime of the requests object graph.\r\n\r\nIf this works well, we might even go ahead and add some auto_includes mechanism.\r\nAka on the third access to B->C prefetch that automatically (within bounds)\r\nThis could result in a prefetch hint on relations (please excuse if there already is such thing)\r\naka: prefetch:true or prefetch:100 or prefetch:{min:3, max:100} ... you get the idea\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"}}