Использование большой таблицы поиска - PullRequest
0 голосов
/ 25 апреля 2018

Постановка задачи:

У меня есть две таблицы - Данные (40 столбцов) и LookUp (2 столбца). Мне нужно использовать col10 в таблице данных с таблицей поиска, чтобы извлечь соответствующее значение. Однако я не могу сделать равное соединение. Мне нужно соединение на основе like / содержит, поскольку значения в таблице поиска содержат только частичное содержимое значения в таблице данных, а не полное значение. Следовательно, требуется некоторое регулярное соответствие.

Размер данных:

  1. Таблица данных: приблизительно - 2,3 миллиарда записей (1 ТБ данных)
  2. Таблица поиска: приблизительно 1,4 миллиона записей (50 МБ данных)

Подход 1:

1.Использование базы данных (я использую Google Big Query) - Соединение, основанное на подобии, занимает около 3 часов, но не возвращает результата. Я считаю, что объединение на основе регулярных выражений приводит к декартовому объединению.

  1. Использование Apache Beam / Spark - я попытался создать Trie для таблицы поиска, которая затем будет передаваться / транслироваться на рабочие узлы. Однако при таком подходе я получаю OOM, поскольку создаю слишком много строк. Я пытался увеличить память до 4 ГБ + на рабочий узел, но безрезультатно. Я использую Trie, чтобы извлечь самый длинный совпадающий префикс.

Я открыт для использования других технологий, таких как Apache spark, Redis и т. Д. Посоветуйте мне, как мне решить эту проблему.

Эту обработку необходимо выполнять ежедневно, поэтому необходимо оптимизировать время и ресурсы.

1 Ответ

0 голосов
/ 26 апреля 2018

Однако я не могу сделать равное объединение

Ниже просто хочу дать вам идею для изучения в чистом BigQuery вашей equi join связанной проблемы

Этоосновываясь на предположении, которое я вывел из ваших комментариев, и охватывает случай использования, когда вы ищете самое длинное совпадение справа налево - совпадения в середине не квалифицированы

Подход состоит в том, чтобы изменить обаполя url (col10) и shorten_url (col2), а затем SPLIT () их и UNNEST () с сохранением позиций

UNNEST(SPLIT(REVERSE(field), '.')) part WITH OFFSET position  

После этого вы можете выполнить equi join, который потенциально может решить вашу проблему внекоторые расширяются.
ТАК, вы ПРИСОЕДИНЯЕТЕСЬ по частям и позициям, затем GROUP BY с оригинальным url и shorten_url, оставляя только те группы, ИМЕЯ количество совпадений, равное количеству частей в shortteded_url, и, наконец, вы GROUP BY по URL и оставляя только запись с наибольшим числомсоответствующих частей

Надеюсь, что это может помочь: o)

Это для BigQuery Standard SQL

#standardSQL
WITH data_table AS (
  SELECT 'cn456.abcd.tech.com' url UNION ALL
  SELECT 'cn457.abc.tech.com' UNION ALL
  SELECT 'cn458.ab.com'
), lookup_table AS (
  SELECT 'tech.com' shortened_url, 1 val UNION ALL
  SELECT 'abcd.tech.com', 2
), data_table_parts AS (
  SELECT url, x, y
  FROM data_table, UNNEST(SPLIT(REVERSE(url), '.')) x WITH OFFSET y
), lookup_table_parts AS (
  SELECT shortened_url, a, b, val, 
    ARRAY_LENGTH(SPLIT(REVERSE(shortened_url), '.')) len
  FROM lookup_table, UNNEST(SPLIT(REVERSE(shortened_url), '.')) a WITH OFFSET b
)
SELECT url, 
  ARRAY_AGG(STRUCT(shortened_url, val) ORDER BY weight DESC LIMIT 1)[OFFSET(0)].* 
FROM (
  SELECT url, shortened_url, COUNT(1) weight, ANY_VALUE(val) val
  FROM data_table_parts d
  JOIN lookup_table_parts l
  ON x = a AND y = b
  GROUP BY url, shortened_url
  HAVING weight = ANY_VALUE(len)
)
GROUP BY url  

с результатом как

Row url                 shortened_url   val  
1   cn457.abc.tech.com  tech.com        1    
2   cn456.abcd.tech.com abcd.tech.com   2    
...