#python #sql #django #postgresql #indexing
#python #sql #django #postgresql #индексирование
Вопрос:
У меня есть очень простая база данных Postgres, которая выглядит так (она определена в Django, но это не имеет значения):
class Country:
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# Not important
# name = models.TextField(nullable=False)
class City:
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# name = models.TextField(nullable=False)
country = models.ForeignKey(Country)
class Street:
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# name = models.TextField(nullable=False)
city = models.ForeignKey(City)
# Just some boolean field
is_big = models.BooleanField(nullable=False)
Я хочу запросить количество «больших» улиц в стране. Это делается так:
SELECT COUNT(*)
FROM Street
INNER JOIN City
ON Street.city_id = City.id
WHERE Street.is_big = true AND City.country_id = 'xxxxxxx'::uuid
Всего в базе данных около ~ 20 стран, ~ 5000 городов и ~ 2 миллионов улиц, что немного, но этот запрос может занять иногда 1-2 секунды.
Какой индекс я должен добавить, чтобы ускорить этот запрос?
Комментарии:
1. Проиндексируйте внешний ключ и все поля из
WHERE
предложения.2. Как обычно, вам нужно проанализировать, ОБЪЯСНИТЬ, ПРОАНАЛИЗИРОВАТЬ вывод вашего запроса, чтобы найти, что замедляет его в вашем конкретном случае. Пример из понимания ОБЪЯСНЯЕТ «20 Поможет ли здесь индекс?», Где запрос с предложением WHERE » должен прочитать 99,95% таблицы. В этом случае он никогда не будет использовать индекс »
Ответ №1:
Это ваш запрос:
SELECT COUNT(*)
FROM Street s JOIN
City c
ON s.city_id = c.id
WHERE s.is_big = true AND c.country_id = 'xxxxxxx'::uuid;
Для этого есть два возможных подхода. Однако я подозреваю, что ни один из них не будет работать действительно хорошо во всех случаях — я предполагаю, что в некоторых странах много больших улиц.
Первый подход заключается в фильтрации по большим улицам: street(is_big, city_id)
и city(id, country_id)
. Второй — фильтровать по конкретной стране: city(country_id, id)
и street(city_id, is_big)
.
Если база данных статична, то запрос может использовать сканирование только по индексу — при условии, что данные «видны».
Комментарии:
1. Я не уверен, что это вообще значит
2. @user972014 . . . Это дает вам два набора индексов, чтобы попробовать.