-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize Complex Structures #28
Comments
I don't know whether to be impressed or horrified. ;-) Counting up the number of "relationships" being asked for, I would guess there should be only about 40 queries total, not 484. Any chance of sending along a query log so I can see what's going on? |
@pmjones Did you missed to login to http://pen-paper.geekity.com/creator/2/ . It has the debug bar which shows the sql queries. Or are you looking for the real sql query log? |
@harikt I did miss it, but looking at it now, it might still be easier to look at the real log (if possible) -- copying the text out of the debug bar is not as readable as I'd like. |
Is this what you're looking for? https://dl.dropboxusercontent.com/u/2696023/creator.log If you need something different let me know. :-) |
Yes thanks! I might go so far as to install pen-and-paper and try to work through what Atlas is doing myself. Thanks for bringing this to my attention. (Also, I'm happy that Atlas actually works in that very complex scenario.) |
@andrewshell my head is whirling.. So it looks first probably need to understand the DB better. There is some where something got missing. The publisher and game liner etc is the one repeating. |
Yes, @harikt is on the right track here. If I comment out everything but
... then I get only 4 queries, which is just what I'd expect: the master, plus 3 relateds (rpg_book_creators, rpg_book, credit). So there's something going on with publisher and game_line. |
Reading through the query log this is what's happening: First, it queries for the single Creator which only has 1 creator_id (creator_id = 2). |
I think it's how the relationships work:
Atlas can look up all of the RpgBookCreators which is a oneToMany from Creator. There is a single Publisher for a single RpgBook and there is only a single RpgBook for each RpgBookCreator. |
I wonder if it's because the N+1 mitigation is working only on the layer "just below" the current Record or RecordSet. Something to do with RpgBook having only one Record, so it queries for the one Publisher, but then it goes on to the next RpgBook for RpgBookCreator, and issues a query for that RpgBook. I'll delve a bit more deeply. |
Yes, that does appear to be what's going on. You get back one record for the first ManyToOne, as you should. But the subsequent ManyToOne is now operating on a single record, not a record set, so it issues a single query to get the subsequent one record. I'm not sure how to mitigate that; it would require looking at results that have not been collected yet, from an arbitrarily distant subsequent query, and then collating the results into that arbitrarily distant set of objects. I suspect we'd see the same result for 1:1 having a subsequent 1:1, or *:1 having 1:1, or 1:1 having *:1. |
I didn't think it would be an easy fix. I figured the current performance was already good enough and if I really needed an improvement I could either add a caching layer or do the stitching myself. If we can figure out a solution it would be a killer feature. :-) |
Good enough. :-) |
It's a more generalized problem. |
Awesome! |
@andrewshell Do me a favor: try out the "n1records" branch in your project, and let me know if my new fixes solve the N+1 problem for you. |
@pmjones Looks like it! No breakage and went from 484 queries to 32. Looks like a win! |
SWEET. I'll merge back to the main branch later on. Thanks for the good reporting! |
All merged to 0.x -- switch back to that at your convenience. Thanks again! |
I'm working on a site that has a very complex interrelated database structure.
https://github.com/andrewshell/pen-paper-2/tree/0.1.0
Here is the most complex query in my application:
CreatorsAtlasRepository::getCreatorById
The complexity comes in the creator join tables. They can't really be manyToMany because there are multiple relationships off of them.
In this particular query, Publisher is a sub-table under 4 different tables. GameLine is also under 4 different tables.
In total, there are 20 different tables that will need to be queried in order to assemble this structure.
I installed DebugBar and on a page like Creator Monte Cook (username
pen-paper
& passwordhoopla
), it shows that there were 484 queries. Many of those are selecting single rows frompublishers
orgame_lines
.I understand that this is an extreme example of a query with Atlas and completely understand if your response is "This is a weird edge case that I'm not supporting".
But since Paul is the author of "Solving The N+1 Problem In PHP" I thought he'd want to know. ;-)
I would also like to note that even with all those queries the page (with query cache disabled) renders in about 1.6 seconds. 👍
Most likely these pages wouldn't change very often and would be cached so it's not an emergency or anything.
The text was updated successfully, but these errors were encountered: