2016-05-25 61 views
1

目前SQLAlchemy中的ORM查詢中的某些表上的TABLESAMPLE是否可能?如何使用SQLAlchemy 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作爲我的數據庫。

回答

4

更新

SQLAlchemy 1.1 and newer support TABLESAMPLE爲selectables。 FromClause元件具有方法FromClause.tablesample()(認爲Table S)和sqlalchemy.tablesample()功能可以與所有selectables一起使用,例如聲明性模型的類:

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 discussionTABLESAMPLE支持。由於SQLAlchemy的非常extensible,這裏是一個非常簡單(讀:可能不適合所有情況的工作)執行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 

argument應該是暫時只是代表0之間的百分比浮動100,儘管PostgreSQL會接受任何實值表達式​​。另一方面,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, [...]) 
+0

謝謝你寫的代碼示例了太多!我對一個指針很滿意,這只是超出了預期。 –