Django Индекс не учтен для существующей таблицы - PullRequest
2 голосов
/ 04 мая 2020

Я использую существующую mysql таблицу с Django Rest Framework. Для большой таблицы mysql простой запрос на выборку в phpmysql занимает 10 секунд без индекса. С индексом по полю он занимает 3 мс. Поэтому я добавил индекс вручную с помощью phpMysql, но Django все еще занимает 10 секунд для выполнения запроса и не видит новый индекс. Я добавил db_index=True в своем поле в models.py. Но сделать миграцию не увидел никаких обновлений на моих уже существующих моделях, и скорость по-прежнему 10 с. (Любые обновления таблиц, созданных с помощью django, работают очень хорошо) Я решил удалить свой индекс вручную с помощью phpmysql, и я сам создал файл 0002_initial.py с этим кодом:

из django .db импорт миграций, модели

класс Миграция (migrations.Migration):

dependencies = [
    ('tutorials', '0001_initial'), # or last mig
]

operations = [
    migrations.RunSQL("CREATE INDEX idx_last_name ON crm_users (us_last_name(64))")
]

Я запустил миграцию, и django создает индекс в таблице. Но Django все еще требуется 10 секунд, чтобы выполнить один выбор в индексированном поле, и он не использует индекс mysql.

Мой вопрос: где и как я могу сказать django, чтобы использовать индексы для существующих таблица не создана Django? Большое спасибо!

1 Ответ

2 голосов
/ 04 мая 2020

Ваш запрос:

profils = profils.filter(us_last_name__icontains=name).using('crm')

Может не использовать индекс .

Действительно вы здесь стремиться выполнить поиск подстроки . Например, 'bar' будет соответствовать, если столбец содержит 'foobarqux'. Там нет индексов, которые поддерживают это. Например, дерево префиксов или дерево суффиксов могут соответствовать строкам, которые начинаются или заканчиваются данной строкой соответственно.

Для подстроки это не вариант. Можно определить некоторые сложные индексы, но они потребуют больших накладных расходов при вставке, обновлении и удалении элементов и потребуют относительно большой объем памяти по сравнению с фактически сохраненными данными. Поэтому не похоже, что база данных будет реализовывать их. Идеальный индекс обычно быстр при поиске и обновлений и часто занимает небольшой объем памяти по сравнению с реальной таблицей, поскольку в противном случае загрузка индекса заняла бы уже значительное количество времени.

Запрос, который может использовать индекс, таков:

profils = profils.filter(<b>us_last_name=name</b>).using('crm')

Но тогда, конечно, вы выполняете точное совпадение.

Это не имеет ничего общего с Django. Если вы попытаетесь в оболочке базы данных выполнить запрос, например:

SELECT * FROM crm_users WHERE <b>us_last_name LIKE '%bar%'</b>

, это займет примерно столько же времени.

В поисковых системах часто "подготавливают" данные в базы данных, собирая н-грамм [вики] , что позволяет затем быстро фильтровать на входе. Пакет вроде django-haystack [readthedocs] может помочь с этим.

...