But I would like to know about the second one. Does it search through all the Picture table in the database to find all the pictures that have post=p or is the information available when I get p in the first query?
Short answer: by default a ForeignKey
adds an index, making retrievals quite fast (logarithmic in the number of values, and linear in the number of reverse records).
That depends on whether the database constructs an index on the ForeignKey
. By default Django will construct an index. This means that it does not only stores the rows of the table, but also a datastructure that allows fast lookup of all the rows that have a specific value.
The implementation of the index can be database dependent. In MySQL it will by default use a BTREE
, this means that for the lookup of a value, it takes approximately O(log n) to obtain the collection, and O(k) with k the number of items with that foreign key to retrieve all. But other index structures exist, like some sort of hashtable, that even allow (slightly) faster lookup, although a hashtable for example will not be that efficient to retrieve all elements with a ForeignKey
less than a given number.
You can also add an index on other columns, for example:
class Post(models.Model):
name = models.CharField(max_length=25, db_index=True, unique=True)
So now retrieving all Post
objects with a name a given name, will run faster as well.
Using indices is of course not "free": it means that each time you insert or remove a record, the index need to be altered as well (typically this also requires O(log n)). If you update a record by changing the value of the foreign key, then that index needs to be altered as well. So indices provide a significant speedup, but one should aim to only put indexes on column on which one performs a lookup frequently, since otherwise the cost of "maintaining" the index can be larger than the gain of speeding up the lookup process.