Оптимизация SqlAlchemy для объектных моделей только для чтения

У меня сложная сеть объектов, созданных из базы данных sqlite с использованием сопоставлений ORM sqlalchemy. У меня довольно много глубоко вложенных:

for parent in owner.collection: for child in parent.collection: for foo in child.collection: do lots of calcs with foo.property 

Мое профилирование показывает мне, что аппаратура sqlalchemy занимает много времени в этом прецеденте.

Дело в том, что я никогда не меняю объектную модель (сопоставленные свойства) во время выполнения, поэтому, как только они загружаются, мне не нужна аппаратура или вообще какие-либо накладные расходы на sqlalchemy. После долгих исследований я думаю, что, возможно, мне придется клонировать набор объектов «чистого питона» из уже загруженных «инструментальных объектов», но это было бы болью.

Производительность здесь действительно важна (это симулятор), поэтому, возможно, написав эти слои, как C-расширения, используя sqlite api, было бы лучше всего. Есть предположения?

  • проблема при передаче данных с использованием объекта сеанса SQLAlchemy в цикле
  • Как преобразовать результат SqlAlchemy в JSON?
  • В чем разница между Model.query и session.query (Model) в SQLAlchemy?
  • Таблица сопоставления SQLAlchemy с столбцами non-ascii для класса
  • Flask-SQLAlchemy - Когда создаются и уничтожаются таблицы / базы данных?
  • SQLAlchemy - способ сопоставления с единственным (или рассчитанным) свойством
  • Как создать db mysql с sqlalchemy
  • Возвращение отдельных строк в SQLAlchemy с помощью SQLite
  • 3 Solutions collect form web for “Оптимизация SqlAlchemy для объектных моделей только для чтения”

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

    Если вы хотите создать дешевые чистые клоны python, разделите объект dict с исходным объектом:

     class CheapClone(object): def __init__(self, original): self.__dict__ = original.__dict__ 

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

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


    Нашел быстрый и грязный способ, который, по крайней мере, несколько работает на 0,5,8 и 0,6. Не тестировал его с наследованием или другими функциями, которые могли бы плохо взаимодействовать. Кроме того, это затрагивает некоторые непубличные API, поэтому остерегайтесь поломки при смене версий.

     from sqlalchemy.orm.attributes import ClassManager, instrumentation_registry class ReadonlyClassManager(ClassManager): """Enables configuring a mapper to return instances of uninstrumented classes instead. To use add a readonly_type attribute referencing the desired class to use instead of the instrumented one.""" def __init__(self, class_): ClassManager.__init__(self, class_) self.readonly_version = getattr(class_, 'readonly_type', None) if self.readonly_version: # default instantiation logic doesn't know to install finders # for our alternate class instrumentation_registry._dict_finders[self.readonly_version] = self.dict_getter() instrumentation_registry._state_finders[self.readonly_version] = self.state_getter() def new_instance(self, state=None): if self.readonly_version: instance = self.readonly_version.__new__(self.readonly_version) self.setup_instance(instance, state) return instance return ClassManager.new_instance(self, state) Base = declarative_base() Base.__sa_instrumentation_manager__ = ReadonlyClassManager 

    Пример использования:

     class ReadonlyFoo(object): pass class Foo(Base, ReadonlyFoo): __tablename__ = 'foo' id = Column(Integer, primary_key=True) name = Column(String(32)) readonly_type = ReadonlyFoo assert type(session.query(Foo).first()) is ReadonlyFoo 

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

    Попробуйте использовать один запрос с JOINs вместо петель python.

    Python - лучший язык программирования в мире.