Можно ли изменить запрос Apache Spark JDBC connector?

#python #sql #oracle #apache-spark #pyspark

#питон #sql #Oracle #apache-spark #pyspark #python

Вопрос:

Я использую PySpark для чтения данных из таблицы Oracle DB. То, как я это делаю, так это:

  profiles = spark.read.jdbc(
            url=db_url,
            table='(select /*  SCN_ASCENDING */ '
                  'data, sys_hashval from profiles)',
            properties=connection_details,
            predicates=predicates_list)
  

Spark преобразует это в запрос такой формы:

 SELECT "ID","DATA"
FROM (
  select /*  FULL(profiles) SCN_ASCENDING */ id, data, sys_hashval
  from profiles
)
WHERE sys_hashval >= 10840662 and sys_hashval < 11012736
  

Что вызывает проблемы, потому что подсказка, добавленная мной к внутреннему подзапросу, отсутствует во внешнем запросе, добавленном Spark.
Можно ли как-нибудь изменить внешний запрос? Или Spark не дает возможности контролировать это?

Спасибо

Ответ №1:

Я не уверен, как изменить этот запрос из PySpark, но есть несколько способов изменить запрос со стороны базы данных. Например, пакет DBMS_ADVANCED_REWRITE позволяет вам заменить один запрос на другой.

 begin
    sys.dbms_advanced_rewrite.declare_rewrite_equivalence
    (
        name             => 'spark_rewrite_1',
        source_stmt      => q'[SELECT "ID","DATA"
FROM (
  select /*  FULL(profiles) SCN_ASCENDING */ id, data, sys_hashval
  from profiles
)
WHERE sys_hashval >= 10840662 and sys_hashval < 11012736]',
        destination_stmt => q'[SELECT /*  SCN_ASCENDING */ "ID","DATA"
FROM (
  select /*  FULL(profiles) */ id, data, sys_hashval
  from profiles
)
WHERE sys_hashval >= 10840662 and sys_hashval < 11012736 and 1=1]',
        validate         => false,
        rewrite_mode     => 'TEXT_MATCH'
    );
end;
/
  

Этот пакет может быть сложным в использовании, потому что вам нужно получить точный текст запросов. Если литералы изменятся, вам потребуется отдельная перезапись, так что, надеюсь, вы сможете контролировать эти числа. И окончательный запрос должен иметь отличие, отличное от подсказок, вот почему я добавил 1=1 . Вам также могут потребоваться права доступа к пакету, и вам может понадобиться администратор базы данных для выполнения этой команды: grant execute on dbms_advanced_rewrite to your_username;

Если приведенный выше код не работает, запросы также могут быть принудительно изменены с помощью подсказок через профили SQL, SQL translation framework или, возможно, с помощью подсказки, которая ссылается на имя внешнего блока запроса.

Ответ №2:

Oracle ищет ID столбец в подзапросе. Это, скорее всего, ошибка.

Я не знаком со Spark, но мы можем попробовать добавить первичный ключ profiles в ваш подзапрос, вот так:

 select /*  FULL(profiles) SCN_ASCENDING */ data, sys_hashval, pk_name "ID"
from profiles
  

Просто измените pk_name с помощью первичного ключа вашей profiles таблицы.

Комментарии:

1. Я отредактировал свой запрос. Это не было скопировано правильно, извините. Проблема не в том, что внешний запрос не находит столбец. Запрос выполняется правильно. Проблема в том, что я хочу, чтобы подсказка была добавлена к внешнему запросу с помощью spark.