У меня есть искровое задание, которое получает данные из таблицы в SQL Server и генерирует
предложение where для предикатов, передаваемых функцией jdbc
в таблицу назначения, которая находится в MySQL. Я использую Spark 2.3 в Cloudera.
Код предиката:
.jdbc(s"<dest_db_url>", config.destTable,predicate, destOptions)
Предложение where, которое я передаю массиву predicate
, выглядит так:
Array(
"(composite_primary_key1='ABCD' AND composite_primary_key2='123') OR
(composite_primary_key1='EFGH' AND composite_primary_key2='456')",
"(composite_primary_key1='WXYZ' AND composite_primary_key2='342') OR
(composite_primary_key1='QWYS' AND composite_primary_key2='664')"
)
Фрагмент кода, генерируемый выше predicate
, равен
val predicates = sourceData
.map(row => s"(composite_primary_key1='${row.composite_primary_key1}' AND composite_primary_key2='${row.composite_primary_key2}')")
.reduce(_+" OR "+_)
Запрос, который отправляется в MySQL, выглядит так:
SELECT * FROM myTable WHERE
(composite_primary_key1 IS NOT NULL AND composite_primary_key2 IS NOT NULL) AND
((composite_primary_key1='ABCD' AND composite_primary_key2='123') OR
(composite_primary_key1='EFGH' AND composite_primary_key2='456'))
Условие (Composite_primary_key1 НЕ НЕДЕЙСТВИТЕЛЬНО И СЛОЖНОЕ_ПРИМЯ_КЛЮЧ2 НЕ НУЖНО) Условие добавляется перед фактическим предикатом. Из-за этого запрос сканирует намного больше строк, чем требуется в MySQL, что делает запрос неэффективным.
Это поведение довольно случайное. Иногда spark генерирует правильный запрос, например
SELECT * FROM myTable WHERE
((composite_primary_key1='ABCD' AND composite_primary_key2='123') OR
(composite_primary_key1='EFGH' AND composite_primary_key2='456'))
Без проверок NULL. Невозможно выяснить это случайное поведение.