programing

SQLAlchemy ORM을 사용하여 데이터베이스를 효율적으로 업데이트

sourcejob 2023. 7. 18. 21:41
반응형

SQLAlchemy ORM을 사용하여 데이터베이스를 효율적으로 업데이트

저는 새로운 애플리케이션을 시작하고 ORM, 특히 SQL 화학을 사용하려고 합니다.

예를 들어 데이터베이스에 'foo' 열이 있는데 이 열을 증분하려고 합니다.straight sqlite에서 이것은 쉽습니다.

db = sqlite3.connect('mydata.sqlitedb')
cur = db.cursor()
cur.execute('update table stuff set foo = foo + 1')

SQLAlchemy SQL-builder에 해당하는 것을 알게 되었습니다.

engine = sqlalchemy.create_engine('sqlite:///mydata.sqlitedb')
md = sqlalchemy.MetaData(engine)
table = sqlalchemy.Table('stuff', md, autoload=True)
upd = table.update(values={table.c.foo:table.c.foo+1})
engine.execute(upd)

이것은 조금 느리지만, 별로 들어있지 않습니다.

SQL 화학 ORM 접근 방식에 대한 최선의 추측은 다음과 같습니다.

# snip definition of Stuff class made using declarative_base
# snip creation of session object
for c in session.query(Stuff):
    c.foo = c.foo + 1
session.flush()
session.commit()

이것은 옳은 일이지만, 다른 두 개가 접근하는 것보다 50배 조금 더 오래 걸립니다.모든 데이터를 메모리로 가져와야 작동할 수 있기 때문이라고 생각합니다.

SQLAlchemy의 ORM을 사용하여 효율적인 SQL을 생성할 수 있는 방법이 있습니까?아니면 다른 파이썬 ORM을 사용합니까?아니면 다시 손으로 SQL을 작성해야 합니까?

SQL Lchemy의 ORM은 SQL 계층과 함께 사용되어야 하며 숨길 필요가 없습니다.그러나 동일한 트랜잭션에서 ORM과 일반 SQL을 사용할 때는 한 두 가지 사항을 염두에 두어야 합니다.기본적으로 ORM 데이터 수정은 세션에서 변경 내용을 플러시할 때만 데이터베이스에 영향을 미칩니다.반대로 SQL 데이터 조작 문은 세션에 있는 개체에 영향을 주지 않습니다.

그래서 만약 당신이

for c in session.query(Stuff).all():
    c.foo = c.foo+1
session.commit()

명령대로 데이터베이스에서 모든 개체를 가져오고 모든 개체를 수정한 다음 데이터베이스에 대한 변경 내용을 플러시할 시간이 되면 행을 하나씩 업데이트합니다.

대신 다음 작업을 수행해야 합니다.

session.execute(update(stuff_table, values={stuff_table.c.foo: stuff_table.c.foo + 1}))
session.commit()

이는 예상대로 하나의 쿼리로 실행되며, 최소한 기본 세션 구성이 커밋 시 세션의 모든 데이터가 만료되기 때문에 오래된 데이터 문제는 없습니다.

거의 출시된 0.5 시리즈에서는 다음 방법을 사용하여 업데이트할 수 있습니다.

session.query(Stuff).update({Stuff.foo: Stuff.foo + 1})
session.commit()

그러면 기본적으로 이전 스니펫과 동일한 SQL 문이 실행되지만 변경된 행도 선택하고 세션의 오래된 데이터도 만료됩니다.업데이트 후 세션 데이터를 사용하지 않는 경우 추가할 수도 있습니다.synchronize_session=False업데이트 문으로 이동하여 선택한 항목을 제거합니다.

session.query(Clients).filter(Clients.id == client_id_list).update({'status': status})
session.commit()

사용해 보십시오 =)

sqlalchemy를 사용하여 업데이트하는 몇 가지 방법이 있습니다.

1) for c in session.query(Stuff).all():
       c.foo += 1
   session.commit()

2) session.query(Stuff).update({"foo": Stuff.foo + 1})
   session.commit()

3) conn = engine.connect()
   table = Stuff.__table__
   stmt = table.update().values({'foo': Stuff.foo + 'a'})
   conn.execute(stmt)
   conn.commit()

다음은 필드를 수동으로 매핑하지 않고 동일한 문제를 해결하는 방법의 예입니다.

from sqlalchemy import Column, ForeignKey, Integer, String, Date, DateTime, text, create_engine
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm.attributes import InstrumentedAttribute

engine = create_engine('postgres://postgres@localhost:5432/database')
session = sessionmaker()
session.configure(bind=engine)

Base = declarative_base()


class Media(Base):
  __tablename__ = 'media'
  id = Column(Integer, primary_key=True)
  title = Column(String, nullable=False)
  slug = Column(String, nullable=False)
  type = Column(String, nullable=False)

  def update(self):
    s = session()
    mapped_values = {}
    for item in Media.__dict__.iteritems():
      field_name = item[0]
      field_type = item[1]
      is_column = isinstance(field_type, InstrumentedAttribute)
      if is_column:
        mapped_values[field_name] = getattr(self, field_name)

    s.query(Media).filter(Media.id == self.id).update(mapped_values)
    s.commit()

미디어 인스턴스를 업데이트하려면 다음과 같은 작업을 수행할 수 있습니다.

media = Media(id=123, title="Titular Line", slug="titular-line", type="movie")
media.update()

객체 생성 측면에서 오버헤드 때문이라면 SA로는 전혀 속도를 낼 수 없을 것입니다.

관련 개체를 로드하기 때문에 로드가 느리면 로드 작업을 수행할 수 있습니다.참조로 인해 많은 개체가 생성되고 있습니까? (즉, 회사 개체를 가져오면 관련된 모든 사용자 개체도 가져옵니다.)

철저한 테스트를 통해, 저는 다음을 시도할 것입니다.

for c in session.query(Stuff).all():
     c.foo = c.foo+1
session.commit()

(IIRC, commit()는 플러시() 없이 작동합니다.

저는 때때로 큰 쿼리를 수행한 다음 파이썬에서 반복하는 것이 많은 쿼리보다 최대 2배 더 빠를 수 있다는 것을 발견했습니다.쿼리 개체를 반복하는 것이 쿼리 개체의 all() 메서드에서 생성된 목록을 반복하는 것보다 효율성이 떨어집니다.

[아래 설명에 유의하십시오. 이는 작업 속도를 전혀 높이지 않았습니다.

언급URL : https://stackoverflow.com/questions/270879/efficiently-updating-database-using-sqlalchemy-orm

반응형