Предположим, у меня есть искровой фрейм данных df
с некоторыми столбцами (id, ...) и строка sqlFilter
с фильтром SQL, например. "id is not null"
.
Я хочу отфильтровать кадр данных df
на основе sqlFilter
, т.е.
val filtered = df.filter(sqlFilter)
Теперь я хочу получить список из 10 идентификаторов из df
, которые были удалены фильтром.
В настоящее время я использую соединение "leftanti" для достижения этой цели, т.е.
val examples = df.select("id").join(filtered.select("id"), Seq("id"), "leftanti")
.take(10)
.map(row => Option(row.get(0)) match { case None => "null" case Some(x) => x.toString})
Однако, это действительно медленно.
Я предполагаю, что это может быть реализовано быстрее, потому что спарк должен иметь только список для каждого раздела
и добавить идентификатор в список, когда фильтр удаляет строку, а список содержит менее 10 элементов. После того, как действие после
Фильтр завершается, спарк должен собрать все списки с разделов, пока у него не будет 10 идентификаторов.
Я хотел использовать аккумуляторы, как описано здесь ,
но я потерпел неудачу, потому что я не мог найти, как разобрать и использовать sqlFilter
.
Кто-нибудь знает, как я могу улучшить производительность?
Обновление
Рамеш Махарджан предложил в комментариях инвертировать SQL-запрос, т.е.
df.filter(s"NOT ($filterString)")
.select(key)
.take(10)
.map(row => Option(row.get(0)) match { case None => "null" case Some(x) => x.toString})
Это действительно улучшает производительность, но не на 100% эквивалентно.
Если есть несколько строк с одним и тем же идентификатором, идентификатор будет в конечном итоге в примерах, если одна строка будет удалена из-за фильтра. С присоединением leftantit это не заканчивается в примерах, потому что id все еще в filtered
.
Тем не менее, это нормально для меня.
Мне все еще интересно, можно ли создать список "на лету" с аккумуляторами или чем-то подобным.
Обновление 2
Другая проблема с инвертированием фильтра - это логическое значение UNKNOWN в SQL, поскольку NOT UNKNWON = UNKNOWN, т. Е. NOT(null <> 1) <=> UNKNOWN
, и, следовательно, эта строка не отображается ни в фильтрованном кадре данных, ни в инвертированном кадре данных.