Nano Hash - криптовалюты, майнинг, программирование

Слишком много выборок сделано в отношениях один к одному в SQLALchemy

import sqlalchemy as db
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Entity(Base):
    __tablename__ = 'entity'
    id = db.Column(db.Integer, primary_key=True, index=True)
    a = db.Column(db.Integer, index=True)
    b = db.Column(db.Integer)

    foos = relationship('Foo')


class Foo(Base):
    __tablename__ = 'foo'
    id = db.Column(db.Integer, primary_key=True, index=True)

    entity_id = db.Column(db.Integer, db.ForeignKey('entity.id'))

    entity = relationship('Entity', uselist=False)
    bars = relationship('Bar')


class Bar(Base):
    __tablename__ = 'bar'
    id = db.Column(db.Integer, primary_key=True, index=True)

    foo_id = db.Column(db.Integer, db.ForeignKey('foo.id'))

    foo = relationship('Foo', uselist=False)

engine = db.create_engine('sqlite:///:memory:', echo=False)
session = sessionmaker(bind=engine)()
Base.metadata.create_all(engine)

def relationship_optimizing():
    engine.echo = True
    entity = Entity(a=1000000, b=10000000000)
    foo = Foo(entity=entity)
    bar = Bar(foo=foo)
    session.add_all([entity, foo, bar])
    session.commit()
    bla = session.query(Entity).filter_by(id=bar.foo.entity_id).one()
    session.commit()

relationship_optimizing()

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

Посмотрите на код. Когда я пытаюсь получить объект "bla", SQLAlchemy генерирует 3 запроса:

SELECT bar.id AS bar_id, bar.foo_id AS bar_foo_id 
FROM bar 
WHERE bar.id = 1

SELECT foo.id AS foo_id, foo.entity_id AS foo_entity_id 
FROM foo 
WHERE foo.id = 1

SELECT entity.id AS entity_id, entity.a AS entity_a, entity.b AS entity_b 
FROM entity 
WHERE entity.id = 1

Я пытался использовать lazy="joined" и lazy="subquery" во всех отношениях, но первые 2 запроса все еще присутствуют. Я хочу избавиться от них. Окончательный запрос может использовать соединения, но это должен быть единственный запрос.

Это игрушечный пример, но в реальном проекте слишком много таких запросов-паразитов, когда я просто обращаюсь к полям отношений. Мой проект выполняет много небольших запросов (в основном с одной записью), поэтому производительность очень низкая :(


Ответы:


1

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

Нет причин совершать коммиты посреди работы, и это, в первую очередь, противоречит цели транзакций. Если все, что вам нужно сделать, это заполнить id для ваших объектов, используйте session.flush(), который обновляет базу данных в соответствии с вашими объектами — без фиксации.

session.commit() решает эту проблему только потому, что он (обязательно) сначала сбрасывает, но по какой-то причине стало апокрифическим советом фиксировать вместо сбрасывания, когда все, что вам нужно, это автоматические ключи.

09.06.2015
  • Спасибо. Не могли бы вы привести больше примеров, когда я должен сбросить сеанс вместо его фиксации? Когда требуется коммит? 09.06.2015
  • Например, у меня есть пользователь, который совершает такие действия, как подключение услуги, списание денег и так далее. В настоящее время после каждой пользовательской операции я совершаю коммит. Должен ли я совершать только после выхода из программы? Коммит медленнее, чем флеш? 09.06.2015
  • вы должны зафиксировать, когда вы хотите, чтобы пакет работы был успешным или неудачным как единое целое. так что одно действие пользователя, вероятно, должно существовать в рамках одной транзакции, да. в противном случае, если что-то пойдет не так позже, часть данных изменилась, но не все, и теперь ваши данные могут быть в плохом состоянии. 10.06.2015
  • Новые материалы

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

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..