Подтвердить что ты не робот

Работает ли искривление предиката с JDBC?

В соответствии с этим

Catalyst применяет логические оптимизации, такие как предикат pushdown. оптимизатор может вытеснять предикаты фильтра вниз в источник данных, позволяя физическому исполнению пропускать нерелевантные данные.

Spark поддерживает подавление предикатов к источнику данных. Эта функция также доступна/ожидается для JDBC?

(Из проверки журналов БД я вижу, что это не поведение по умолчанию прямо сейчас - полный запрос передается в БД, даже если он позже ограничен фильтрами искры)

ДОПОЛНИТЕЛЬНЫЕ ДАННЫЕ

Запуск Spark 1.5 с PostgreSQL 9.4

фрагмент кода:

from pyspark import SQLContext, SparkContext, Row, SparkConf
from data_access.data_access_db import REMOTE_CONNECTION

sc = SparkContext()
sqlContext = SQLContext(sc)

url = 'jdbc:postgresql://{host}/{database}?user={user}&password={password}'.format(**REMOTE_CONNECTION)
sql = "dummy"

df = sqlContext.read.jdbc(url=url, table=sql)
df = df.limit(1)
df.show()

SQL Trace:

< 2015-09-15 07:11:37.718 EDT >LOG:  execute <unnamed>: SET extra_float_digits = 3                                                                                                                      
< 2015-09-15 07:11:37.771 EDT >LOG:  execute <unnamed>: SELECT * FROM dummy WHERE 1=0                                                                                                                   
< 2015-09-15 07:11:37.830 EDT >LOG:  execute <unnamed>: SELECT c.oid, a.attnum, a.attname, c.relname, n.nspname, a.attnotnull OR (t.typtype = 'd' AND t.typnotnull), pg_catalog.pg_get_expr(d.adbin, d.a
drelid) LIKE '%nextval(%' FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON (c.relnamespace = n.oid) JOIN pg_catalog.pg_attribute a ON (c.oid = a.attrelid) JOIN pg_catalog.pg_type t ON (a.a
tttypid = t.oid) LEFT JOIN pg_catalog.pg_attrdef d ON (d.adrelid = a.attrelid AND d.adnum = a.attnum) JOIN (SELECT 15218474 AS oid , 1 AS attnum UNION ALL SELECT 15218474, 3) vals ON (c.oid = vals.oid
 AND a.attnum = vals.attnum)                                                                                                                                                                            
< 2015-09-15 07:11:40.936 EDT >LOG:  execute <unnamed>: SET extra_float_digits = 3                                                                                                                      
< 2015-09-15 07:11:40.964 EDT >LOG:  execute <unnamed>: SELECT "id","name" FROM dummy                                                                                                                   

Я ожидаю, что последний select будет включать в себя предложение limit 1 - но это не

4b9b3361

Ответ 1

Spark DataFrames поддерживает предикат push-down с источниками JDBC, но термин предикат используется в строгом смысле SQL. Это означает, что он охватывает только предложение WHERE. Более того, похоже, что он ограничен логической связью (нет IN и OR я боюсь) и простыми предикатами.

Все остальное, например ограничения, подсчеты, упорядочение, группы и условия, обрабатывается на стороне искры. Одно из предостережений, уже рассмотренных на SO, заключается в том, что df.count() или sqlContext.sql("SELECT COUNT(*) FROM df") переведен на SELECT 1 FROM df и требует как существенной передачи данных, так и обработки с использованием Spark.

Означает ли это, что это потерянная причина? Не совсем. В качестве аргумента table можно использовать произвольный подзапрос. Это менее удобно, чем преданное нажатие, но в остальном работает очень хорошо:

n = ... # Number of rows to take
sql = "(SELECT * FROM dummy LIMIT {0}) AS tmp".format(int(n))
df = sqlContext.read.jdbc(url=url, table=sql)

Примечание

Такое поведение может быть улучшено в будущем, как только Data Source API v2 будет готов: