Recently I've been working with larger datasets than I previously have in the past, which has led me to learn much more about how ActiveRecord handles mysql queries. When using a gem or a library that does a lot of behind the scenes magic, there is a tendency to rely on that magic; until it bites us in the ass. I got myself into such a situation with
delete_all on a related model.
I changed a bit of our code in the PhishMe app to use
delete_all instead of
destroy_all or a method we previously used to destroy in batches. I wanted this process to be faster and since we didn't need the callbacks
delete_all would work perfectly.
I expected that the call for Model.related_mode.delete_all to produce the following mysql query:
In fact, the produced mysql that was created by the ActiveRecord query was:
The above query normally wouldn't cause any issue and you might not even noticed the slowed down query, but if you have thousands of records it blows up, and not gracefully.
When you hit the threshold of the number of records that can be chained, ActiveRecord spits out a "StackLevel too deep". (facepalm) After I thought about it, the issue was obvious. The stack really is too deep. I did actually ask mysql to chain all the methods. I didn't expect this behavior because I had never considered the ramifications of the
Model.related_model.delete_all call I was making.
I'm becoming very interested in how our ActiveRecord calls translate into mysql queries. It's easy with "magic" gems to ignore the underlying behavior.