При создании внешней таблицы в кустах я могу указать местоположение на определенные файлы в каталоге?

Я определил таблицу как таковую:

create external table PageViews (Userid string, Page_View string)
partitioned by (ds string)
row format as delimited fields terminated by ','
stored as textfile location '/user/data';

Я не хочу, чтобы все файлы в каталоге /user/data использовались как часть таблицы. Возможно ли, чтобы я сделал следующее?

location 'user/data/*.csv'

Ответ 1

Я столкнулся с этой проблемой, когда у меня возникла аналогичная проблема. Я смог решить это, используя специальный SerDe. Затем я добавил свойства SerDe, которые управляли тем, что RegEx применяется к шаблонам имен файлов для любой конкретной таблицы.

Пользовательский SerDe может показаться излишним, если вы имеете дело только со стандартными файлами CSV, у меня был более сложный формат файла. Тем не менее это очень жизнеспособное решение, если вы не уклоняетесь от написания Java. Это особенно полезно, когда вы не можете реструктурировать данные в своем хранилище, и вы ищете очень специфичный шаблон файла среди непропорционально большого набора файлов.

> CREATE EXTERNAL TABLE PageViews (Userid string, Page_View string)  
> ROW FORMAT SERDE 'com.something.MySimpleSerDe' 
> WITH SERDEPROPERTIES ( "input.regex" = "*.csv")
> LOCATION '/user/data';

Ответ 2

То, что сказал kmosley, верно. На данный момент вы не можете выборочно выбирать определенные файлы как часть вашей таблицы Hive. Однако есть два способа обойти это.

Вариант 1: Вы можете переместить все файлы csv в другой каталог HDFS и создать над ним таблицу Hive. Если он работает лучше для вас, вы можете создать подкаталог (скажем, csv) в вашем текущем каталоге, в котором хранятся все файлы CSV. Затем вы можете создать таблицу Hive поверх этого подкаталога. Имейте в виду, что любые таблицы Hive, созданные поверх родительского каталога, НЕ будут содержать данные из подкаталога.

Вариант 2: Вы можете изменить свои запросы, чтобы использовать виртуальный столбец с именем INPUT__FILE__NAME.

Ваш запрос будет выглядеть примерно так:

SELECT 
   *
FROM
   my_table
WHERE
   INPUT__FILE__NAME LIKE '%csv';

Неправильный эффект этого подхода заключается в том, что запрос Hive должен будет обрабатывать все данные, присутствующие в каталоге, хотя вы только заботитесь о конкретных файлах. Запрос не будет отфильтровывать файлы на основе предиката с помощью INPUT__FILE__NAME. Он просто отфильтровывает записи, которые не поступают из соответствия предикату, используя INPUT__FILE__NAME во время фазы карты (следовательно, отфильтровывая все записи из определенных файлов), но мапперы также будут работать с ненужными файлами. Он даст вам правильный результат, может иметь некоторые, возможно, незначительные служебные накладные расходы.

Преимущество этого подхода заключается в том, что вы можете использовать одну и ту же таблицу Hive, если в вашей таблице было несколько файлов, и вы хотели иметь возможность запрашивать все файлы из этой таблицы (или ее раздела) в нескольких запросах и подмножестве файлы в других запросах. Для этого вы можете использовать виртуальный столбец INPUT__FILE__NAME. В качестве примера: если раздел в вашем каталоге HDFS /user/hive/warehouse/web_logs/ выглядит следующим образом:

/user/hive/warehouse/web_logs/dt=2012-06-30/
   /user/hive/warehouse/web_logs/dt=2012-06-30/00.log
   /user/hive/warehouse/web_logs/dt=2012-06-30/01.log
   .
   .
   .
   /user/hive/warehouse/web_logs/dt=2012-06-30/23.log

Скажем, ваше определение таблицы выглядело следующим образом:

CREATE EXTERNAL TABLE IF NOT EXISTS web_logs_table (col1 STRING)
PARTITIONED BY (dt STRING)
LOCATION '/user/hive/warehouse/web_logs';

После добавления соответствующих разделов вы можете запросить все журналы в разделе с помощью запроса типа:

SELECT
   *
FROM
   web_logs_table w
WHERE
   dt='2012-06-30';

Однако, если вы только заботились о журналах с первого часа дня, вы можете запросить журналы в течение первого часа, используя запрос, например:

SELECT
   *
FROM
   web_logs_table w
WHERE 
   dt ='2012-06-30'
   AND INPUT__FILE__NAME='00.log';

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

В обоих приведенных выше случаях использования, имеющих дополнительный раздел для часа или домена, также решит проблему, без необходимости использовать виртуальный столбец. Однако могут существовать некоторые компромиссы в дизайне, которые требуют от вас не создавать подразделы. В этом случае, возможно, лучше всего использовать виртуальный столбец INPUT__FILE__NAME.

Выбор между двумя параметрами:

Это действительно зависит от вашего варианта использования. Если вы никогда не позаботитесь о файлах, которые вы пытаетесь исключить из таблицы Hive, использование Option 2, вероятно, является излишним, и вы должны исправить структуру каталогов и создать таблицу Hive поверх каталога, содержащего файлы, которые вам интересны.

Если файлы, которые вы в настоящее время исключаете, соответствуют тому же формату, что и другие файлы (так что все они могут быть частью одной и той же таблицы Hive), и вы можете видеть, что вы пишете запрос, который будет анализировать все данные в каталоге, а затем перейдите в Вариант 2.

Ответ 3

Нет, вы не можете этого сделать. Существует открытый билет JIRA, позволяющий выбирать регулярные выражения для включенных файлов для таблиц Hive (https://issues.apache.org/jira/browse/HIVE-951).

На данный момент лучше всего создать таблицу в другом каталоге и просто скопировать файлы, которые вы хотите запросить.