如何使用SQLAlchemy进行TABLESAMPLE?

Tim*_*mol 1 python postgresql sqlalchemy

当前是否可以TABLESAMPLE在SQLAlchemy中的ORM查询中的某些表上使用?

我能找到的最接近的是Query.suffix_with(*suffixes),但是将后缀放在查询的末尾,而不是表的末尾。

如果有帮助,这是我的用例:

我的查询当前是:

query = session.query(A).options(
    subqueryload(A.rel1),
    subqueryload(A.rel2)
).filter(A.id >= min_id, A.id < max_id, [...]) 
Run Code Online (Sandbox Code Playgroud)

并且我想TABLESAMPLE在桌子上,A这样我就可以A使用某些过滤器有效地仅加载的子集及其对应的关系。我正在使用PostgreSQL 9.5作为数据库。

Ilj*_*ilä 5

更新资料

SQLAlchemy 1.1和TABLESAMPLE对可选项的较新支持FromClause元素具有方法FromClause.tablesample()(think Table),并且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)))
Run Code Online (Sandbox Code Playgroud)

那里有一个轻微的不对称tablesample(A, ...),其中A是一个声明性类,返回一个TableSample从句,如果用作模型,则必须使用别名。否则,它的作用类似于FromClause,例如Table基础模型类。


之前

在撰写本文时,似乎还没有关于TABLESAMPLE支持的讨论。由于SQLAlchemy的可扩展性很强,因此这是tablesample支持的一种非常简单的(阅读:可能不适用于所有用例):

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
Run Code Online (Sandbox Code Playgroud)

argument应是暂时只是表示为了方便在0和100之间的百分比浮动,但是PostgreSQL的会接受任何实数表达。在seed另一方面被编译等文字蟒值必须与被包裹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, [...])
Run Code Online (Sandbox Code Playgroud)

  • 也感谢您编写示例代码!我对指针很满意,这超出了预期。 (2认同)