Могу ли я легко переиграть Django ORM 'iexact', чтобы использовать LOWER () вместо UPPER ()? - PullRequest
6 голосов
/ 27 января 2012

Использование Django 1.3x.

В настоящее время у меня есть очень, очень большой и очень, очень активный набор данных Postgres, в котором важная колонка имеет индекс lower(column).

Я только что понял, что некоторые распространенные запросы были довольно медленными, потому что ORM Django генерирует запрос для поля как blah = UPPER(column), когда я использую iexact для сопоставления этого поля.

Есть ли простой способ заставить ORM использовать lower() вместо этого, или мне нужно перейти на необработанный SQL для этого?

Спасибо!

[побочный вопрос к комментариям: есть ли хорошая причина, которую упустили из виду, чтобы использовать upper() в индексе, а не lower()?]

Ответы [ 2 ]

7 голосов
/ 27 января 2012

Интересная ситуация здесь.Я никогда не переставал думать об этом раньше.Похоже, что использование UPPER для iexact поиска было введено еще в ревизии 8536 , в ответ на тикет 3575 , почти три года назад.До этого Django использовал ILIKE для этих типов поиска.

Я просмотрел код бэкэнда, и единственное, что я могу найти, что указывает на любую причину UPPER против LOWER, похоже,что Oracle по умолчанию использует прописные буквы при обработке данных без учета регистра.Поскольку остальные агностики, Django решил использовать значение по умолчанию UPPER, чтобы охватить все базы.

Другое впечатление, которое я получил от просмотра исходного кода, заключалось в том, что вы не сможете обойти использованиеUPPER.Это буквально повсюду, а не только при запросе базы данных.Расширение строки upper в Python также используется довольно часто.

Я бы сказал, что вам лучше всего просто создать индекс с upper(column) или вместо него и пойти выпить.

3 голосов
/ 17 января 2015

Попробуйте .extra(), прежде чем перейти к .raw()

MyModel.objects.extra(where=["lower(mycol)=%s"], params=['foo'])
...