정밀한 웹 애플리케이션을 빨리 빌,도는 목록의 Id 를 개체 목록

StackOverflow https://stackoverflow.com/questions/444475

  •  22-07-2019
  •  | 
  •  

문제

나는 순서의 Id 나는 원하는 검색 할 수 있습니다.그것은 간단하다:

session.query(Record).filter(Record.id.in_(seq)).all()

더 좋은 방법이 있을까요?

도움이 되었습니까?

해결책

코드 absolutety 괜찮습니다.

IN 처럼 무리의 X=YOR 고 매우 빠른 속에서 현대적인 데이터베이스가 있습니다.

그러나,귀하의 Id 목록은 길,만들 수 있는 쿼리를 조금 더 효율적으로 전달하여 하위 쿼리를 반환하는 목록의 Id 입니다.

다른 팁

이 코드를 수정하는 것은 완전히 괜찮습니다.그러나,누군가가 나에게 묻는 일부 시스템을 막아의 두 방식의 큰에 대를 사용하여 얻()개인 Id 입니다.

만약 누군가가 정말을 피하기 위해 노력하고 선택한 다음 최고의를 할 수 있는 방법을 설정할 필요한 개체를 메모리에 있습니다.와 같은,당신은 테이블의 요소입니다.휴식을 작품으로 덩어리,등의,주문정 작업의 기본 키로,또는 날짜 범위에 의해,무엇이든 다음,로드 모두에 대한 덩어리를 로컬로 캐시:

 all_ids = [<huge list of ids>]

 all_ids.sort()
 while all_ids:
     chunk = all_ids[0:1000]

     # bonus exercise!  Throw each chunk into a multiprocessing.pool()!
     all_ids = all_ids[1000:]

     my_cache = dict(
           Session.query(Record.id, Record).filter(
                 Record.id.between(chunk[0], chunk[-1]))
     )

     for id_ in chunk:
         my_obj = my_cache[id_]
         <work on my_obj>

는 현실 세계를 사용한 경우.

하지만 또한 일부를 보여주는 정밀한 웹 애플리케이션을 빨리 빌 API,우리가 할 수 있는 기능을 하는지에 대한 기록이 없어 및 지역을 얻을 사람들을 위해 우리는 않습니다.여기에는 것입니다:

from sqlalchemy import inspect


def get_all(session, cls, seq):
    mapper = inspect(cls)
    lookup = set()
    for ident in seq:
        key = mapper.identity_key_from_primary_key((ident, ))
        if key in session.identity_map:
            yield session.identity_map[key]
        else:
            lookup.add(ident)
    if lookup:
        for obj in session.query(cls).filter(cls.id.in_(lookup)):
            yield obj

여기에는 데모:

from sqlalchemy import Column, Integer, create_engine, String
from sqlalchemy.orm import Session
from sqlalchemy.ext.declarative import declarative_base
import random

Base = declarative_base()


class A(Base):
    __tablename__ = 'a'
    id = Column(Integer, primary_key=True)
    data = Column(String)

e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)

ids = range(1, 50)

s = Session(e)
s.add_all([A(id=i, data='a%d' % i) for i in ids])
s.commit()
s.close()

already_loaded = s.query(A).filter(A.id.in_(random.sample(ids, 10))).all()

assert len(s.identity_map) == 10

to_load = set(random.sample(ids, 25))
all_ = list(get_all(s, A, to_load))

assert set(x.id for x in all_) == to_load

당신이 사용하는 경우 복합 기본 키로 사용할 수 있습니다 tuple_, 에서와 같이,

from sqlalchemy import tuple_
session.query(Record).filter(tuple_(Record.id1, Record.id2).in_(seq)).all()

참고로 이것은에서 사용할 수 없습 SQLite(참조하십시오 doc).

내가 권하고 싶을 살펴 SQL 생산하고 있습니다.당신은 인쇄 할 수 있습 str(query)하여 그것을 참조하십시오.

내가 알고있는 이상적인 방법 그 일의 표준 SQL.

다른 하나의 방법으로;는 경우 그것은 합리적인 기대하는 개체는 질문에는 이미 로드 세션당신은에 액세스하기 전에 그들을 같은 트랜잭션에서,당신은 실시간으로 공동 작업:

map(session.query(Record).get, seq)

는 경우에는 해당 개체에 이미 존재하는,이것은 훨씬 더 빠르고,이후 없을 쿼리를 검색하는 해당 개체;다른 한편으로는 경우보다 더 작은 수의 사람들 개체가 로드,그것은 훨씬,훨씬 더 느린 것이기 때문에 발생 쿼리당 인스턴스가 누락 대신에,하나의 쿼리에 대한 모든 개체입니다.

이 때 유용할 수 있습니다 당신이 하고 있는 joinedload() 쿼리에 도달하기 전에 위의 단계는,확신할 수 있도록 그들이 탑재되었다.일반적으로,당신은 사용해야에서 솔루션을 질문에 기본적으로만 이 솔루션을 때 당신이 볼 수있는 쿼리를 위한 동일한 개체습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top