Перейти к содержимому

Индексируемые поля в Odoo: практическое руководство для разработчиков и консультантов

Как работает атрибут index в ORM Odoo, когда его стоит включать и как это влияет на производительность базы данных
6 марта 2026 г. от
Индексируемые поля в Odoo: практическое руководство для разработчиков и консультантов
Dasolo
| Комментариев пока нет

Введение


Если вы когда‑либо правили определения полей в Odoo, наверняка замечали в коде что‑то вроде index=True. На первый взгляд это мелочь — будто пометка «на потом». На практике же одно такое свойство может серьёзно повлиять на скорость отклика системы при фильтрации, поиске и навигации по большим объёмам данных.


Этот материал объясняет, что означает индексированное поле в модели данных Odoo, как это отражается на уровне базы данных и в каких случаях имеет смысл включать индекс при разработке модулей. Независимо от того, пишете ли вы кастомный модуль или анализируете существующую систему, понимание механики индексов поможет принимать более взвешенные решения.

Что такое индексируемое поле в Odoo


В ORM Odoo поле считается индексируемым, когда его определение содержит параметр index=True. Это сигнал для Odoo — при установке или обновлении модуля создать в PostgreSQL индекс типа B‑tree для соответствующего столбца таблицы.


Ниже — упрощённый пример объявления поля в Python, показывающий, как выглядит такая настройка в коде:

class SaleOrder(models.Model):
    _name = 'sale.order'

    reference = fields.Char(string='Reference', index=True)
    state = fields.Selection([...], index=True)
    partner_id = fields.Many2one('res.partner', index=True)

Для конечного пользователя никаких визуальных отличий от индексированного поля не видно: ни в форме, ни в списке нельзя прямо определить, есть ли индекс. Это внутренняя оптимизация на уровне базы данных — прозрачная для интерфейса.


Суть эффекта — уменьшение времени поиска. Когда столбец индексирован, PostgreSQL может быстро находить подходящие записи, особенно на таблицах с тысячами и миллионами строк. Без индекса сервер вынужден просматривать каждую строку (sequential scan), а с индексом обращается к упорядоченной структуре и сразу получает нужные результаты.


Какие типы полей Odoo поддерживают index=True

Практически все скалярные типы в ORM поддерживают параметр index:

  • Char и Text
  • Integer и Float
  • Date и Datetime
  • Selection
  • Many2one (особенно часто индексируются)
  • Boolean

Отношения типа One2many и Many2many не имеют собственного столбца в той же форме, поэтому у них параметр index неприменим. Также вычисляемые поля без store=True не имеют реального столбца в базе и не могут быть индексированы.

Принцип работы поля с индексом


При инициализации или апдейте модуля Odoo перебирает определения полей и синхронизирует схему БД. Для каждого поля с index=True выполняется соответствующий SQL‑запрос на создание индекса в PostgreSQL.


По умолчанию создаётся индекс B‑tree — универсальный тип индекса, оптимальный для операций равенства (=), диапазонных запросов (>, <, BETWEEN) и сортировок. Именно этот набор покрывает большинство фильтров и доменов в Odoo.


Взаимодействие с ORM Odoo

ORM переводит домены Python в SQL‑условия. Если вы пишете домен вроде [('state', '=', 'sale')], то он превращается в WHERE state = 'sale'. Наличие индекса на поле state позволяет PostgreSQL быстро выполнить такое условие без полного сканирования таблицы.


Типичный пример — Many2one. В заказе продаж поле partner_id хранит целочисленный идентификатор партнёра. При фильтре «покупатель = X» запрос выглядит как WHERE partner_id = X. С индексом такой поиск остаётся быстрым даже при сотнях тысяч заказов.


Индексы и скорость записи

Индексы имеют свою цену: при создании, обновлении или удалении записи PostgreSQL обязан обновлять все связанные индексы. На таблицах с большим количеством индексов операции записи замедляются. В большинстве сценариев Odoo это приемлемая плата за ускорение чтения, но индексировать всё подряд — плохая идея.

Опция index='trigram'

Начиная с Odoo 16, параметр index можно указать как строку 'trigram'. Это создаёт GIN‑индекс на основе триграмм с помощью расширения pg_trgm, что ускоряет поиск по шаблону с ILIKE. Полезно для поиска по частичным вхождениям в названиях товаров, партнёров и т. п.


name = fields.Char(string='Product Name', index='trigram')

Это более продвинутая настройка, которую сами разработчики Odoo используют для полей, часто ищущихся по частичным строкам.

Бизнес‑сценарии применения


Ниже — реальные сценарии, где индексирование заметно улучшает работу системы.


1. CRM: фильтрация лидов по менеджеру

В CRM менеджеры постоянно фильтруют воронку по ответственному. Поле user_id на crm.lead индексируется по умолчанию, поэтому фильтрация остаётся быстрой даже при большом количестве лидов. Аналогично — если вы добавляете кастомное поле связи с пользователем или командой, стоит индексировать его при необходимости.


2. Продажи: поиск заказов по статусу

Поле state в sale.order индексировано — это ускоряет загрузку списков подтверждённых заказов или фильтра «ожидает отгрузки» для компаний с интенсивной обработкой заказов. Часто используемые selection‑поля — хорошая цель для индекса.


3. Склад: отслеживание перемещений по товару

В системах с большим количеством складских операций таблица перемещений может вырасти до миллионов строк. Индекс на product_id в stock.move позволяет быстро получать все движения по конкретному товару; без него отчёты по прослеживаемости станут крайне медленными.


4. Бухгалтерия: выписки по контрагенту

Бухгалтеры часто открывают проводки по отдельному клиенту или поставщику. Индекс на partner_id в account.move.line делает такие выборки оперативными — это критично для отчётов с историей за много лет.


5. Кастомные модули: поля‑ссылки для трассировки

При разработке собственных модулей часто добавляют поля‑ссылки (внешний номер, код проекта и т. п.). Если по таким полям пользователи регулярно фильтруют, добавление index=True — простой способ сохранить скорость работоспособности по мере роста данных.


Создание или настройка индексируемого поля


Как добавить в Python (разработка модулей)

Включить index=True в определении поля в Python очень просто — достаточно передать аргумент при объявлении:


from odoo import models, fields

class ProjectTask(models.Model):
    _inherit = 'project.task'

    x_external_ref = fields.Char(
        string='External Reference',
        index=True,
        help='Reference number from the external system'
    )

После добавления поля обновите модуль командой odoo-bin -u your_module_name или через интерфейс Apps — Odoo создаст соответствующий индекс в базе.


Индекс можно добавить и к уже существующему полю, переопределив его в наследуемой модели, но это требует осторожности, чтобы не нарушить поведение оригинального поля.


Через Odoo Studio

Studio позволяет нетехническим пользователям создавать поля через интерфейс, но там нет опции включить индекс при создании. Поля Studio сохраняются как ручные поля без index=True по умолчанию.


Если поле, созданное в Studio, нужно индексировать, правильный путь — превратить кастомизацию в полноценный Python‑модуль и добавить index=True в код. Как правило, этим занимается разработчик.


Добавление индекса напрямую в PostgreSQL

Иногда, чтобы оптимизировать боевую базу без обновления модуля, администратор БД создаёт индекс вручную через SQL:

CREATE INDEX CONCURRENTLY idx_sale_order_partner_id
ON sale_order (partner_id);

Опция CONCURRENTLY позволяет избежать блокировки таблицы при создании индекса — важный момент в production. Тем не менее такие правки нужно синхронизировать с определением модуля, иначе при следующем обновлении несинхронизированные изменения могут привести к несоответствию кода и структуры БД.


Рекомендации и практики


Индексируйте поля, которые участвуют в доменах поиска

Если поле часто используется в доменных фильтрах — в фильтрах списков, автоматических действиях, cron‑задачах или как зависимость вычисляемого поля — это признак, что его стоит индексировать. На практике это чаще всего Many2one, state или поля‑коды/референсы.


Ориентируйтесь на соглашения Odoo

Лучший ориентир — сами стандартные модули Odoo. Посмотрите, какие поля индексированы в sale.order, account.move, stock.move — выбор разработчиков Odoo основан на реальной нагрузке и опыте множества боевых баз.


Всегда индексируйте Many2one в моделях с большим объёмом данных

Для моделей, которые со временем накапливают большое количество записей (проводки, складские перемещения, строки заказов), индекс для Many2one, используемого при фильтрации, почти всегда оправдан. Затраты на единичный индекс обычно перекрываются выигрышем при чтении.


Рассмотрите триграммы для текстового поиска

На Odoo 16+ при частом поиске по частичным вхождениям в Char‑полях (названия товаров, контрагентов, номера документов) стоит применить index='trigram'. Триграммовые индексы оптимизированы под ILIKE и похожие запросы.


Проверьте, что индекс действительно используется

После добавления индекса выполните EXPLAIN ANALYZE для целевого запроса — если планировщик всё ещё выбирает sequential scan, возможно таблица слишком мала, или условия запроса несовместимы с типом индекса.


Документируйте решения об индексировании

В кастомных модулях оставляйте краткие комментарии, почему поле индексировано. Это помогает будущим разработчикам понять мотив и не удалить индекс случайно при рефакторинге.

Типичные ошибки и подводные камни


Индексировать всё подряд — неправильная стратегия

Частая ошибка у новичков — ставить index=True на все поля «на всякий случай». Это контрпродуктивно: индексы занимают место и нагружают операции записи. На таблицах с интенсивными insert/update лишние индексы могут замедлить систему.


Индексирование маленьких таблиц

На таблицах с несколькими сотнями строк планировщик PostgreSQL зачастую считает последовательное сканирование быстрее индекса. Индексы начинают давать заметный эффект на тысячах записей. Для небольших lookup‑таблиц индекс лишний.


Забыть обновить модуль после добавления index=True

Просто добавить index=True в код недостаточно — нужно обновить модуль (-u module_name или через интерфейс). Пропуск этого шага — частая причина путаницы в dev/stage/production средах.


Ожидание ускорения ILIKE с обычным B‑tree

Обычный B‑tree не помогает при запросе типа ILIKE '%слово%' с ведущим подстановочным символом — такой запрос не использует B‑tree. Для быстрого поиска по частям строки применяйте index='trigram' или решения полнотекстового поиска.


Не учитывать вычисляемые сохраняемые поля

Вычисляемые поля с store=True имеют физический столбец и могут индексироваться. Иногда это упускают, хотя такие поля, используемые в доменах и отчётах, можно и нужно индексировать для повышения производительности.

Заключение


Небольшая настройка в определении поля — index=True — может оказать большое влияние на поведение базы при росте объёма данных. При правильном использовании индексы поддерживают быстрый поиск и отзывчивые представления; при неосмотрительном — лишь добавляют издержки.


Краткий вывод: индексируйте поля, регулярно участвующие в доменах, особенно Many2one в высоконагруженных моделях. Следуйте выбранным Odoo примерам, избегайте лишнего индексирования для маленьких или неиспользуемых полей. Если вы на Odoo 16+, подумайте о index='trigram' для полей с поиском по частичным строкам.


Лучше продумать стратегию индексирования в начале проекта, чем искать и устранять медленные запросы в уже рабочей системе.

Работаете над внедрением Odoo?


В Dasolo мы помогаем компаниям внедрять, настраивать и оптимизировать Odoo. Будь то разработка модулей, улучшение производительности существующей инстанции или планирование нового проекта — мы предлагаем практическую экспертную поддержку на каждом этапе.


Если у вас медленные запросы, сложные кастомизации или вы хотите совет по лучшим практикам разработки Odoo, мы готовы помочь. Свяжитесь с командой Dasolo и расскажите, над чем вы работаете.

Индексируемые поля в Odoo: практическое руководство для разработчиков и консультантов
Dasolo 6 марта 2026 г.
Поделиться этой записью
Войти оставить комментарий