Mysql
 sql >> база данни >  >> RDS >> Mysql

Как да подобрим производителността на заявките в Django администраторско търсене на свързани полета (MySQL)

След много проучвания открих, че проблемът идва от това как е изградена заявката за търсене за полето за търсене на администратор (в ChangeList клас). При търсене с няколко термина (думи, разделени с интервал) всеки термин се добавя към QuerySet чрез свързване на нов filter() . Когато има едно или повече свързани полета в search_fields , създадената SQL заявка ще има много JOIN верижни един след друг с много JOIN за всяко свързано поле (вижте моя свързан въпрос за някои примери и повече информация). Тази верига от JOIN има ли така, че всеки термин ще се търси само в подмножеството на филтъра за данни по предшестващия термин И най-важното е, че свързаното поле трябва да има само един термин (срещу необходимостта да има ВСИЧКИ термини), за да направи съвпадение. Вижте Обхващане на многостойностни взаимоотношения в документите на Django за повече информация по тази тема. Почти съм сигурен, че това е желаното поведение през повечето време за полето за търсене на администратор.

Недостатъкът на тази заявка (с включени свързани полета) е, че вариацията в производителността (време за изпълнение на заявката) може да бъде наистина голяма. Зависи от много фактори:брой търсени термини, търсени термини, вид търсене на поле (VARCHAR и т.н.), брой полета за търсене, данни в таблиците, размер на таблиците и т.н. С правилната комбинация е лесно да имате заявка, която ще отнеме почти цяла вечност (заявка, която отнема повече от 10 минути, за мен е заявка, която отнема цяла вечност в контекста на това поле за търсене).

Причината, поради която може да отнеме толкова време, е, че базата данни трябва да създаде временна таблица за всеки термин и да я сканира предимно изцяло, за да търси следващия термин. Така че това се добавя много бързо.

Възможна промяна, която да направите, за да подобрите производителността, е И всички термини в един и същи filter() . По този начин те ще имат само едно JOIN по свързано поле (или 2, ако е много към много) вместо много повече. Тази заявка ще бъде много по-бърза и с наистина малка вариация на производителността. Недостатъкът е, че свързаните полета ще трябва да имат ВСИЧКИ термини за съвпадение, така че можете да получите по-малко съвпадения в много случаи.

АКТУАЛИЗАЦИЯ

Както беше попитано от trinchet ето какво е необходимо за промяна на поведението при търсене (за Django 1.7). Трябва да замените get_search_results() от администраторските класове, където искате този вид търсене. Трябва да копирате целия код на метода от основния клас (ModelAdmin ) към вашия собствен клас. След това трябва да промените тези редове:

for bit in search_term.split():
    or_queries = [models.Q(**{orm_lookup: bit})
                  for orm_lookup in orm_lookups]
    queryset = queryset.filter(reduce(operator.or_, or_queries))

Към това:

and_queries = []
for bit in search_term.split():
    or_queries = [models.Q(**{orm_lookup: bit})
                  for orm_lookup in orm_lookups]
    and_queries.append(Q(reduce(operator.or_, or_queries)))
queryset = queryset.filter(reduce(operator.and_, and_queries))

Този код не е тестван. Оригиналният ми код беше за Django 1.4 и просто го адаптирах за 1.7 тук.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как правилно да затворя връзката с източник на данни?

  2. mysql брои записи от две таблици в една заявка?

  3. МАКС. ДЪЛЖИНА НА MYSQL CONCAT

  4. Избиране на част от поле с регулярен израз

  5. Как да комбинирам две MySQL колони в една колона?