[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"glossary-orm::ru":3,"gloss-cluster-orm::ru":20,"gloss-next-orm::ru":9},{"slug":4,"category":5,"name":6,"definition":7,"meta_desc":8,"faq":9,"schema_markup":9,"related":10},"orm","data-infra","ORM (объектно-реляционное отображение)","ORM (Object-Relational Mapper, объектно-реляционный маппер) — это библиотека, которая переводит данные между таблицами и строками реляционной базы данных и собственными объектами и классами приложения, позволяя разработчику писать `User.where(email: \"a@b.com\")` или `$user->posts()->where('published', true)->get()` вместо ручного написания SQL-строк для каждого запроса. Почему это важно для разработчиков AI\u002FSaaS-продуктов: ORM (Eloquent в Laravel, Prisma и Drizzle в экосистеме Node\u002FTypeScript, SQLAlchemy в Python, ActiveRecord в Rails) — это то, как подавляющее большинство современных SaaS-бэкендов ежедневно взаимодействует со своей базой данных, поскольку они значительно ускоряют разработку, обеспечивают типобезопасность (особенно Prisma и Drizzle, которые генерируют типы TypeScript напрямую из схемы базы данных) и централизуют миграции схемы. Применительно к AI-функциям те же ORM-модели, что представляют строку `User` или `Document`, обычно несут в себе и колонку `embedding` (через pgvector), а также связи, используемые для объединения структурированных бизнес-данных с результатами векторного поиска в одном месте. Как это работает: ORM сопоставляет каждую таблицу базы данных с классом\u002Fмоделью, каждую строку — с экземпляром этого класса, а каждый столбец — со свойством, и переводит цепочки методов или синтаксис query builder в реальный SQL, отправляемый в базу данных «под капотом». У этого удобства есть хорошо известный побочный эффект — проблема N+1 запросов: наивный перебор списка объектов с обращением к связанному объекту у каждого (например, блок на Ruby `posts.each { |p| p.author.name }`) запускает по одному запросу на каждую итерацию вместо одного эффективного join или пакетного запроса — незаметно на демо с 10 строками, катастрофично в продакшене с 10 000 строк. Большинство зрелых ORM предоставляют синтаксис для «жадной» (eager) загрузки специально для того, чтобы разработчики могли явно объединять запросы связанных данных и избегать этой ловушки (`.with('author')` в Eloquent, `include` в Prisma). Практический пример: эндпоинт дашборда AI-SaaS для управления проектами перебирает 200 задач и для каждой отдельно запрашивает имя исполнителя — итого 201 обращение к базе данных, и эндпоинт отвечает за 4 секунды. Переписывание запроса с eager loading — `Task::with('assignee')->where('project_id', $id)->get()` — сводит это к 2 запросам (один для задач, один пакетный для всех исполнителей), и тот же эндпоинт отвечает менее чем за 100 мс. Проблему N+1 стоит выделить особо, потому что ORM позволяют случайно написать её в коде, который выглядит абсолютно идиоматично — ничто в `p.author.name` внутри цикла не выглядит как проблема производительности при чтении, именно поэтому команды всё чаще добавляют инструменты автоматического обнаружения N+1 (например, `preventLazyLoading()` в Laravel для непродакшен-окружений), чтобы ловить это на код-ревью, а не полагаться на то, что человек заметит проблему при ручном просмотре кода.","ORM позволяет разработчикам запрашивать и изменять реляционную БД через нативные объекты языка программирования вместо написания сырого SQL.",null,[11,14,17],{"slug":12,"name":13},"data-warehouse","Хранилище данных (Data Warehouse)",{"slug":15,"name":16},"index-database","Индекс (база данных)",{"slug":18,"name":19},"postgresql","PostgreSQL",[21,25,28,31,34,38,41,44,47,50,54,57],{"slug":22,"category":5,"name":23,"updated_at":24},"acid","ACID","2026-08-24T02:46:37+00:00",{"slug":26,"category":5,"name":27,"updated_at":24},"ann-search","ANN-поиск (приближённый поиск ближайших соседей)",{"slug":29,"category":5,"name":30,"updated_at":24},"backpressure","Обратное давление (backpressure)",{"slug":32,"category":5,"name":33,"updated_at":24},"batch-processing","Пакетная обработка (Batch Processing)",{"slug":35,"category":5,"name":36,"updated_at":37},"bm25","BM25","2026-08-24T02:46:38+00:00",{"slug":39,"category":5,"name":40,"updated_at":24},"cache","Кэш (Cache)",{"slug":42,"category":5,"name":43,"updated_at":24},"cap-theorem","Теорема CAP (CAP theorem)",{"slug":45,"category":5,"name":46,"updated_at":24},"change-data-capture","Захват изменений данных (CDC)",{"slug":48,"category":5,"name":49,"updated_at":24},"chroma","Chroma",{"slug":51,"category":5,"name":52,"updated_at":53},"chunk-overlap","Перекрытие фрагментов","2026-08-24T03:30:02+00:00",{"slug":55,"category":5,"name":56,"updated_at":24},"columnar-storage","Колоночное хранение",{"slug":58,"category":5,"name":59,"updated_at":24},"connection-pooling","Пулинг соединений (Connection Pooling)"]