SQLAlchemy中的ORM查询中的某些表目前是否可以TABLESAMPLE
?
我能找到的最接近的是Query.suffix_with(*suffixes)
,但这会将后缀放在查询的末尾,而不是放在表的末尾。
如果有帮助,这是我的用例:
我的查询目前是:
query = session.query(A).options(
subqueryload(A.rel1),
subqueryload(A.rel2)
).filter(A.id >= min_id, A.id < max_id, [...])
我希望TABLESAMPLE
位于表格A
上,这样我才能有效加载A
的子集及其对应的关系,以及一些过滤器。我使用PostgreSQL 9.5作为我的数据库。
答案 0 :(得分:4)
SQLAlchemy 1.1 and newer support TABLESAMPLE
可选择的。 FromClause
元素有一个方法FromClause.tablesample()
(思考Table
s)和sqlalchemy.tablesample()
函数可以与所有可选项一起使用,例如声明性模型类:
from sqlalchemy import tablesample, func
from sqlalchemy.orm import aliased
# Create an alias for A that uses SYSTEM sampling method (default)
a_sampled = aliased(A, tablesample(A, 2.5))
# Create an alias for A that uses BERNOULLI sampling method
a_bernoulli = aliased(A, tablesample(A, func.bernoulli(2.5)))
tablesample(A, ...)
中存在轻微的不对称性,其中A
是一个声明性类,返回TableSample
from-clause,如果用作模型,则必须使用别名。否则它就像一个FromClause
,例如模型类底层的Table
。
在撰写本文时似乎no discussion支持TABLESAMPLE
。由于SQLAlchemy非常extensible,这里有一个非常简单的(读取:可能不适用于所有用例)tableample支持的实现:
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql import Alias, FromClause
from sqlalchemy.orm import aliased
class TableSample(Alias):
__visit_name__ = 'tablesample'
def __init__(self, selectable, argument=None, method=None,
seed=None):
super(TableSample, self).__init__(selectable)
self.method = method
self.argument = argument
self.seed = seed
def tablesample(element, argument=None, method=None, seed=None):
if isinstance(element, FromClause):
return TableSample(element, argument=argument, method=method, seed=seed)
else:
return aliased(element, TableSample(element.__table__,
argument=argument, method=method, seed=seed))
@compiles(TableSample)
def compile_tablesample(element, compiler, **kwargs):
s = "%s TABLESAMPLE %s(%s)" % (
compiler.visit_alias(element, **kwargs),
element.method or 'SYSTEM',
element.argument)
if element.seed:
s += " REPEATABLE (%s)" % compiler.process(element.seed, **kwargs)
return s
虽然PostgreSQL接受任何实值表达式,但argument
暂时只是一个表示0到100之间百分比的浮点数。另一方面,seed
被编译,因此文字python值必须用literal()
等包装。
它应该以与aliased
类似的方式使用:
a_sampled = tablesample(A, 2.5)
query = session.query(a_sampled).options(
subqueryload(a_sampled.rel1),
subqueryload(a_sampled.rel2)
).filter(a_sampled.id >= min_id, a_sampled.id < max_id, [...])