Ok, so I extenderd CDbAuthManager to load each of the tables only once. The way I have extended it is so that with these default options nothing will change if you use this instead of CDbAuthManager. So set the extra options like below.

The way CDbAuthManager operates by default is to load each item from the item table and from the relations table with it's own query, discarding the results when done. I call it "singleLoad", and it is very inefficient. Set these two options (singleLoadAuthItems and singleLoadAuthParents) to false will load it all in a query and keep the results.

For the assignments, it will be load from the DB each time a check is made, even if it hasn't changed. How often does the assignments change on the same page request? Set keepAuthAssignments to true to only load it once per request.

And here is the code. checkAccessRecursive() is identical to the CDbAuthManager one, except I moved the part where the parents are loaded to getAuthParents(). I also overwrote getAuthItem() and getAuthAssignments().