Индекс B-Tree
По умолчанию PostgreSQL предоставляет нам очень простой, но эффективный тип индекса - индекс B-дерева. Этот тип индекса является наиболее распространенным в использовании. Он достигает своей цели, создавая древовидную структуру блоков, содержащих ключевые значения в порядке возрастания. Каждый из этих блоков ссылается на еще два дочерних блока, где левые боковые клавиши сохраняют значение меньше, чем текущие клавиши, а правые - больше, чем текущие. Таким образом, поиск значений внутри индекса подходит к простым расчетам сравнения. B-дерево также может обрабатывать запросы равенства и диапазона данных, которые можно отсортировать по порядку.
Простое сравнение между использованием индекса B-дерева и сценариями "без индекса" можно показать в следующем примере.
В приведенном выше примере мы выполняем простой поисковый запрос через фильтрацию about. Используя промежуточное программное обеспечение Django Debug Toolbar, мы можем видеть SQL-запросы, выполненные во время запроса, а также полный план запросов со временем выполнения.
PostgreSQL «решил» использовать последовательное сканирование для извлечения элемента, что просто означает, что ему пришлось сканировать все строки таблицы, чтобы завершить свое действие. Эта практика оказывает явное влияние на значение времени выполнения. Поэтому для повышения производительности мы должны использовать индекс для поля about.
Благодаря Django мы можем внести это изменение непосредственно в нашу модель, применив db_index=True в нужном поле.
class Employee(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
about = models.CharField(max_length=10000, db_index=True)
age = models.SmallIntegerField(null=True)
created = models.DateTimeField(default=timezone.now)
work_experience = models.SmallIntegerField(default=0, null=True)
contact = models.OneToOneField(Contact, on_delete=models.CASCADE, null=True)
department = models.ForeignKey(Department, on_delete=models.CASCADE, default=None, null=True)
def __str__(self):
return f'{self.first_name} {self.last_name}'
После запуска миграции базы данных и повторной отправки запроса мы можем увидеть изменение в выполненном запросе.
На этот раз ядро базы данных использовал метод Index Scan для сканирования индекса, автоматически созданного PostgreSQL. Это означает, что сканирование последовательностей не проводилось, так как система искала дерево индексов, предоставив определенное значение about. Время выполнения на этот раз значительно ниже, снизившись в нашем случае более чем в 2 раза.
На данный момент многие разработчики закончат свою работу, заявив, что нет места для дальнейшего совершенствования. Удивительно, но есть способы еще больше оптимизировать этот запрос, о них мы поговорим в следующем шаге.