#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.