SQLAlchemy를 통해 임의의 행 가져 오기
SQLAlchemy를 사용하여 테이블에서 임의의 행을 어떻게 선택합니까?
이것은 매우 데이터베이스 관련 문제입니다.
PostgreSQL, SQLite, MySQL 및 Oracle이 임의의 함수로 주문할 수 있다는 것을 알고 있으므로 SQLAlchemy에서 이것을 사용할 수 있습니다.
from sqlalchemy.sql.expression import func, select
select.order_by(func.random()) # for PostgreSQL, SQLite
select.order_by(func.rand()) # for MySQL
select.order_by('dbms_random.value') # For Oracle
다음으로 필요한 레코드 수 (예 : 사용 .limit()
)로 쿼리를 제한해야합니다 .
적어도 PostgreSQL에서는 임의의 레코드를 선택하면 심각한 성능 문제가 있음을 명심하십시오. 여기 에 대한 좋은 기사가 있습니다.
orm을 사용하고 테이블이 크지 않고 (또는 캐시 된 행의 양이있는 경우) 데이터베이스에 독립적 이길 원하는 경우 정말 간단한 접근 방식입니다.
import random
rand = random.randrange(0, session.query(Table).count())
row = session.query(Table)[rand]
이것은 약간의 속임수이지만 orm을 사용하는 이유입니다.
데이터베이스에 독립적 인 임의의 행을 가져 오는 간단한 방법이 있습니다. .offset () 사용하십시오. 모든 행을 가져올 필요가 없습니다.
import random
query = DBSession.query(Table)
rowCount = int(query.count())
randomRow = query.offset(int(rowCount*random.random())).first()
테이블은 테이블입니다 (또는 여기에 쿼리를 넣을 수 있음). 몇 개의 행을 원할 경우이를 여러 번 실행하고 각 행이 이전 행과 동일하지 않은지 확인하십시오.
다음은 가장 느린 것부터 가장 빠른 것까지 4 가지 변형입니다. timeit
하단의 결과 :
from sqlalchemy.sql import func
from sqlalchemy.orm import load_only
def simple_random():
return random.choice(model_name.query.all())
def load_only_random():
return random.choice(model_name.query.options(load_only('id')).all())
def order_by_random():
return model_name.query.order_by(func.random()).first()
def optimized_random():
return model_name.query.options(load_only('id')).offset(
func.floor(
func.random() *
db.session.query(func.count(model_name.id))
)
).limit(1).all()
timeit
내 Macbook에서 300 개의 행이있는 PostgreSQL 테이블에 대한 10,000 개의 실행 결과 :
simple_random():
90.09954111799925
load_only_random():
65.94714171699889
order_by_random():
23.17819356000109
optimized_random():
19.87806927999918
를 사용하는 func.random()
것이 모든 결과를 Python의 random.choice()
.
또한 테이블의 크기가 증가함에 따라의 성능 order_by_random()
이 크게 저하됩니다. 이는 ORDER BY
전체 테이블 스캔이 필요하지만 COUNT
in optimized_random()
은 인덱스를 사용할 수 있기 때문 입니다.
일부 SQL DBMS, 즉 Microsoft SQL Server, DB2 및 PostgreSQL 은 SQL : 2003 TABLESAMPLE
절을 구현했습니다 . 버전 1.1에서 SQLAlchemy 에 대한 지원이 추가되었습니다 . 표준은 요구 - 이것은 다른 샘플링 방법을 사용하여 테이블의 예를 반환 허용 SYSTEM
및 BERNOULLI
테이블의 원하는 근사 비율을 반환한다.
SQLAlchemy의에서 FromClause.tablesample()
와 tablesample()
농산물하는 데 사용되는 TableSample
구조를 :
# Approx. 1%, using SYSTEM method
sample1 = mytable.tablesample(1)
# Approx. 1%, using BERNOULLI method
sample2 = mytable.tablesample(func.bernoulli(1))
매핑 된 클래스와 함께 사용할 때 약간의 문제가 있습니다. 생성 된 TableSample
개체는 모델 개체를 쿼리하는 데 사용하기 위해 별칭을 지정해야합니다.
sample = aliased(MyModel, tablesample(MyModel, 1))
res = session.query(sample).all()
많은 답변에 성능 벤치 마크가 포함되어 있으므로 여기에도 몇 가지 간단한 테스트를 포함하겠습니다. 약 백만 개의 행과 단일 정수 열이있는 PostgreSQL의 간단한 테이블을 사용하여 (대략) 1 % 샘플을 선택합니다.
In [24]: %%timeit
...: foo.select().\
...: order_by(func.random()).\
...: limit(select([func.round(func.count() * 0.01)]).
...: select_from(foo).
...: as_scalar()).\
...: execute().\
...: fetchall()
...:
307 ms ± 5.72 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [25]: %timeit foo.tablesample(1).select().execute().fetchall()
6.36 ms ± 188 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [26]: %timeit foo.tablesample(func.bernoulli(1)).select().execute().fetchall()
19.8 ms ± 381 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
SYSTEM
샘플링 방법을 서두르 기 전에 개별 튜플이 아닌 페이지 를 샘플링한다는 것을 알아야합니다 . 따라서 예를 들어 작은 테이블에는 적합하지 않을 수 있습니다.
이것이 내가 사용하는 솔루션입니다.
from random import randint
rows_query = session.query(Table) # get all rows
if rows_query.count() > 0: # make sure there's at least 1 row
rand_index = randint(0,rows_query.count()-1) # get random index to rows
rand_row = rows_query.all()[rand_index] # use random index to get random row
이것은 테이블의 임의의 행을 선택하는 내 기능입니다.
from sqlalchemy.sql.expression import func
def random_find_rows(sample_num):
if not sample_num:
return []
session = DBSession()
return session.query(Table).order_by(func.random()).limit(sample_num).all()
이 솔루션은 임의의 단일 행을 선택합니다.
이 솔루션을 사용하려면 기본 키의 이름이 id 여야합니다. 아직 다음과 같아야합니다.
import random
max_model_id = YourModel.query.order_by(YourModel.id.desc())[0].id
random_id = random.randrange(0,max_model_id)
random_row = YourModel.query.get(random_id)
print random_row
사용중인 데이터베이스에 따라 SQL을 통해 몇 가지 방법이 있습니다.
(나는 SQLAlchemy가이 모든 것을 어쨌든 사용할 수 있다고 생각합니다)
mysql :
SELECT colum FROM table
ORDER BY RAND()
LIMIT 1
PostgreSQL :
SELECT column FROM table
ORDER BY RANDOM()
LIMIT 1
MSSQL :
SELECT TOP 1 column FROM table
ORDER BY NEWID()
IBM DB2 :
SELECT column, RAND() as IDX
FROM table
ORDER BY IDX FETCH FIRST 1 ROWS ONLY
신탁:
SELECT column FROM
(SELECT column FROM table
ORDER BY dbms_random.value)
WHERE rownum = 1
그러나 나는 어떤 표준적인 방법도 모른다
참고URL : https://stackoverflow.com/questions/60805/getting-random-row-through-sqlalchemy
'IT박스' 카테고리의 다른 글
WebDriver-Java를 사용하여 요소 대기 (0) | 2020.11.01 |
---|---|
uint8_t, uint_fast8_t 및 uint_least8_t의 차이점 (0) | 2020.11.01 |
Tkinter 창을 어떻게 닫습니까? (0) | 2020.11.01 |
모달보기 컨트롤러 표시 및 닫기 (0) | 2020.11.01 |
XAML 만 사용하여 단색 삼각형 그리기 (0) | 2020.11.01 |