SQLAlchemy "по умолчанию" против производительности "server_default" - PullRequest
0 голосов
/ 20 сентября 2018

Есть ли преимущество в производительности (или недостаток) при использовании default вместо server_default для отображения значений по умолчанию для столбцов таблицы при использовании SQLAlchemy с PostgreSQL?

Насколько я понимаю, default отображает выражение в INSERT (обычно), а server_default помещает выражение в оператор CREATE TABLE.Похоже, server_default аналогична типичной обработке значений по умолчанию непосредственно в БД, такой как:

CREATE TABLE example (
    id serial PRIMARY KEY,
    updated timestamptz DEFAULT now()
);

... но мне не ясно, является ли более эффективной обработка значений по умолчанию на INSERTили путем создания таблицы.

Будет ли какое-либо улучшение производительности или снижение производительности для вставок строк, если каждый из параметров default в приведенном ниже примере был изменен на server_default?

from uuid import uuid4
from sqlalchemy import Column, Boolean, DateTime, Integer
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql import func

Base = declarative_base()

class Item(Base):
    __tablename__ = 'item'

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4)
    count = Column(Integer, nullable=False, default=0)
    flag = Column(Boolean, nullable=False, default=False)
    updated = Column(DateTime(timezone=True), nullable=False, default=func.now())

ПРИМЕЧАНИЕ. Лучшее объяснение того, когда использовать default вместо server_default, на мой взгляд, не относится к производительности ( см. SO-ответ Майка Байера по теме ).Мое упрощенное резюме этого объяснения состоит в том, что default предпочтительнее, чем server_default, когда ...

  • БД не может обработать выражение, которое вам нужно или вы хотите использовать для значения по умолчанию.
  • Вы не можете или не хотите изменять схему напрямую.

... поэтому остается вопрос о том, следует ли учитывать производительность при выборе между default иserver_default

Ответы [ 2 ]

0 голосов
/ 21 марта 2019

Есть нечто иное, а не просто сравнение производительности двух

Если вам нужно добавить новый столбец create_at (Not Null) в существующую таблицу User снекоторые данные в нем default не будут работать.

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

А при использовании server_default при обновлении БД база данных вставит текущее значение DateTime во все предыдущие существующие данные тестирования.

Так что в этом случае будет работать только server_default.

0 голосов
/ 02 февраля 2019

Невозможно дать вам ответ «это быстрее», потому что производительность для выражения значения по умолчанию может широко варьироваться как на сервере, так и в Python.Функция для получения текущего времени ведет себя не так, как скалярное значение по умолчанию.

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

Обратите внимание, что когда речь идет о выражении SQL, определяющем значение по умолчанию, будь то выражение SQL на стороне клиента, выражение DLL на стороне сервера или триггер, это очень мало влияет набаза данных, откуда исходит выражение значения по умолчанию.Исполнителю запроса необходимо знать, как создавать значения для данного столбца, после того, как он проанализирован из оператора DML или определения схемы, сервер все равно должен выполнить выражение для каждой строки.

Выбор между этимиПараметры редко будут основываться только на производительности, производительность должна составлять максимум , но это один из множества аспектов, которые вы рассматриваете.Здесь задействовано много факторов:

  • default с помощью скалярной или Python-функции напрямую генерирует значение по умолчанию Python, а затем отправляет новое значение на сервер при вставке.Код Python может получить доступ к значению по умолчанию до того, как данные будут вставлены в базу данных.
  • Выражение SQL на стороне клиента, значение server_default и неявные значения по умолчанию и триггеры на стороне сервера имеют серверсгенерируйте значение по умолчанию, которое затем должно быть выбрано клиентом, если вы хотите иметь доступ к нему в том же сеансе SQLAlchemy.Вы не можете получить доступ к значению, пока объект не будет вставлен в базу данных.

    В зависимости от точного запроса и поддержки базы данных, SQLAlchemy может потребоваться выполнить дополнительные запросов SQL, чтобы сгенерироватьпо умолчанию перед оператором INSERT или запустите отдельный SELECT впоследствии, чтобы получить значения по умолчанию, которые были вставлены.Вы можете контролировать, когда это происходит (непосредственно при вставке или при первом доступе после сброса, с помощью конфигурации eager_defaults mapper ).

  • Если несколько клиентов на разных платформах обращаются к нимодна и та же база данных, server_default или другое значение по умолчанию, присоединенное к схеме (например, триггер), гарантирует, что все клиенты будут использовать одни и те же значения по умолчанию, независимо от того, что к значениям по умолчанию, реализованным в Python, не могут получить доступ другие платформы.

При использовании PostgreSQL SQLAlchemy может использовать предложение RETURNING для операторов DML , которое предоставляет клиенту доступ к сгенерированным по умолчанию настройкам на стороне сервера за один шаг.

Таким образом, при использовании значения по умолчанию для столбца server_default, который вычисляет новое значение для каждой строки (не скалярное значение), вы экономите небольшое количество времени на стороне Python и небольшую полосу пропускания сети, поскольку вы неотправка данных для этого столбца в базу данных.База данных может быстрее создавать то же значение или медленнее;это во многом зависит от типа операции.Если вам нужно иметь доступ к сгенерированному значению по умолчанию из Python, в той же транзакции вам придется ждать обратного потока данных, проанализированного SQLAlchemy.Однако все эти детали могут становятся незначительными по сравнению со всем остальным, что происходит при вставке или обновлении строк.

Следует понимать, что ORM не подходит для высокопроизводительной работымассовые вставки или обновления строк ;цитирование из записи SQAlchemy Производительность FAQ :

ORM SQLAlchemy использует шаблон единицы работы при синхронизации изменений в базе данных.Эта модель выходит далеко за рамки простых «вставок» данных.Он включает в себя то, что атрибуты, которые присваиваются объектам, принимаются с использованием системы инструментария атрибутов, которая отслеживает изменения в объектах по мере их внесения, включает в себя то, что все вставленные строки отслеживаются в карте идентификаторов, что приводит к тому, что для каждой строки SQLAlchemy должна получать свои «последний вставленный идентификатор », если он еще не задан, и также включает в себя то, что вставляемые строки сканируются и сортируются по зависимости при необходимости.Объекты также подлежат достаточному учету, чтобы поддерживать все это в рабочем состоянии, что для очень большого числа строк может создать чрезмерное количество времени, затрачиваемое на большие структуры данных, поэтому лучше разбивать их на части.

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

ORM в основном не предназначены для высокопроизводительных массовых вставок - вот почему SQLAlchemy предлагает Core в дополнение к ORM в качестве первоклассного компонента.

Поскольку ORM, такой как SQLAlchemy, поставляется согромные накладные расходы, любые различия в производительности между серверной или Python-стороной по умолчанию быстро исчезают из-за шума операций ORM.

Так что, если вы беспокоитесь о производительности для операций вставки или обновления большого количества, выхотел бы использовать бУльк операции для тех, и включить psycopg2 помощники пакетного выполнения , чтобы действительно получить повышение скорости.При использовании этих массовых операций можно ожидать, что настройки по умолчанию на стороне сервера улучшат производительность, просто сохранив пропускную способность, перемещая данные строк из Python на сервер, но насколько это зависит от точного характера значений по умолчанию.

ЕслиПроизводительность вставки и обновления ORM вне массовых операций - большая проблема для вас, вам нужно проверить ваши конкретные параметры .Я бы начал с SQLAlchemy examples.performance пакета и , чтобы добавить свой собственный набор тестов , используя две модели, которые отличаются только одной конфигурацией server_default и default.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...