Consider asking your database for a list of the first 2000 users whose names start with "Ab" and are older than 20 years. Also they must be male.
Here's a little diagram.
You Program Processor
------------------------------------------------------------------------------
Get the first 2000 users ---------->---------- OK!
--------------------- So I'll go get those records...
WAIT! Also, they have to ---------->---------- Gotcha!
start with "Ab"
--------------------- NOW I'll get them...
WAIT! Make sure they're ---------->---------- Good idea Boss!
over 20!
--------------------- Let's go then...
And one more thing! Make ---------->---------- Anything else? Ugh!
sure they're male!
No that is all. :( ---------->---------- FINE! Getting records!
--------------------- Here you go.
Thanks Postgres, you're ---------->---------- ...
my only friend.
As you can see by this terrible terrible interaction, the "database" isn't actually doing anything until it's ready to handle all the conditions. It's lazy-loading results at each step and applying new conditions each time.
As opposed to getting the first 2000 users, returning them, filtering them for "Ab", returning them, filtering them for over 20, returning them, and filtering for male and finally returning them.
Lazy loading in a nutshell.
head . sort
hasO(n)
complexity due to laziness (notO(n log n)
). See Lazy Evaluation and Time Complexity.