Lors de la création d'une table externe dans hive, puis-je pointer l'emplacement vers des fichiers spécifiques dans un répertoire?
J'ai défini une table en tant que telle:
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';
Je ne veux pas que tous les fichiers du répertoire / user / data soient utilisés dans le cadre de la table. Est-il possible pour moi de faire ce qui suit?
location 'user/data/*.csv'
3 réponses
Je suis tombé sur ce fil quand j'ai eu un problème similaire à résoudre. J'ai pu le résoudre en utilisant un SerDe personnalisé. J'ai ensuite ajouté des propriétés SerDe qui ont guidé ce RegEx à appliquer aux modèles de nom de fichier pour une table particulière.
Un SerDe personnalisé peut sembler exagéré si vous ne traitez que des fichiers CSV standard, j'avais un format de fichier plus complexe à gérer. Pourtant, c'est une solution très viable si vous n'avez pas peur d'écrire du Java. Il est particulièrement utile lorsque vous vous ne parvenez pas à restructurer les données de votre emplacement de stockage et vous recherchez un modèle de fichier très spécifique parmi un ensemble de fichiers disproportionné.
> CREATE EXTERNAL TABLE PageViews (Userid string, Page_View string)
> ROW FORMAT SERDE 'com.something.MySimpleSerDe'
> WITH SERDEPROPERTIES ( "input.regex" = "*.csv")
> LOCATION '/user/data';
Ce que kmosley a dit est vrai. À partir de Maintenant, vous ne pouvez pas choisir sélectivement certains fichiers pour faire partie de votre table de Ruche. Cependant, il y a 2 façons de le contourner.
Option 1: Vous pouvez déplacer tous les fichiers csv dans un autre répertoire HDFS et créer une table de Ruche en plus de cela. Si cela fonctionne mieux pour vous, vous pouvez créer un sous-répertoire (par exemple, csv) dans votre répertoire actuel qui abrite tous les fichiers CSV. Vous pouvez ensuite créer une table de ruche au-dessus de ce sous-répertoire. Gardez à l' rappelez-vous que les tables Hive créées au-dessus du répertoire parent ne contiendront pas les données du sous-répertoire.
Option 2:
Vous pouvez modifier vos requêtes pour utiliser une colonne virtuelle appelée INPUT__FILE__NAME
.
Votre requête ressemblerait à quelque chose comme:
SELECT
*
FROM
my_table
WHERE
INPUT__FILE__NAME LIKE '%csv';
Le mauvais effet de cette approche est que la requête Hive devra parcourir des données entières présentes dans le répertoire même si vous ne vous souciez que de fichiers spécifiques. La requête ne filtrerait pas les fichiers basé sur le prédicat en utilisant INPUT__FILE__NAME
. Il va simplement filtrer les enregistrements qui ne proviennent pas du prédicat en utilisant INPUT__FILE__NAME
pendant la phase de la carte (filtrant par conséquent tous les enregistrements de fichiers particuliers) mais les mappeurs fonctionneraient également sur des fichiers inutiles. Il vous donnera le résultat correct, pourrait avoir des frais généraux de performance, probablement mineurs.
L'avantage de cette approche est que vous pouvez utiliser la même table de la Ruche si vous aviez plusieurs fichiers dans votre table et que vous vouliez le possibilité d'interroger tous les fichiers de cette table (ou sa partition) dans quelques requêtes et un sous-ensemble des fichiers dans d'autres requêtes. Vous pouvez utiliser la colonne virtuelle INPUT__FILE__NAME
pour y parvenir. Comme un exemple:
si une partition dans votre répertoire HDFS /user/hive/warehouse/web_logs/
ressemblait à:
/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
Disons que votre définition de table ressemblait à:
CREATE EXTERNAL TABLE IF NOT EXISTS web_logs_table (col1 STRING)
PARTITIONED BY (dt STRING)
LOCATION '/user/hive/warehouse/web_logs';
Après avoir ajouté les partitions appropriées, vous pouvez interroger tous les journaux de la partition en utilisant une requête comme:
SELECT
*
FROM
web_logs_table w
WHERE
dt='2012-06-30';
Cependant, si vous vous souciez seulement à propos des journaux de la première heure de la journée, vous pouvez interroger les journaux pour la première heure en utilisant une requête comme:
SELECT
*
FROM
web_logs_table w
WHERE
dt ='2012-06-30'
AND INPUT__FILE__NAME='00.log';
Un autre cas d'utilisation similaire pourrait être un répertoire qui contient des journaux web de différents domaines et diverses requêtes doivent analyser les journaux sur différents ensembles de domaines. Les requêtes peuvent filtrer les domaines à l'aide de la colonne virtuelle INPUT__FILE__NAME
.
Dans les deux cas d'utilisation ci-dessus, avoir une sous-partition pour hour OU domain résoudrait également le problème, sans avoir à le faire utilisez la colonne virtuelle. Cependant, il peut exister des compromis de conception qui vous obligent à ne pas créer de sous-partitions. Dans ce cas, sans doute, en utilisant INPUT__FILE__NAME
colonne virtuelle est votre meilleur pari.
Décider entre les 2 options:
Cela dépend vraiment de votre cas d'utilisation. Si vous ne vous souciez jamais des fichiers que vous essayez d'exclure de la table Hive, l'utilisation de l'Option 2 est probablement exagérée et vous devriez réparer la structure du répertoire et créer une table Hive sur haut du répertoire contenant les fichiers qui vous intéressent.
Si les fichiers que vous excluez actuellement suivent le même format que les autres fichiers (ils peuvent donc tous faire partie de la même table de Ruche) et que vous pouvez vous voir écrire une requête qui analyserait toutes les données du répertoire, alors optez pour L'Option 2.
Non, vous ne pouvez pas le faire actuellement. Un ticket Jira est ouvert pour permettre la sélection de regex des fichiers inclus pour les tables Hive ( https://issues.apache.org/jira/browse/HIVE-951).
Pour l'instant, votre meilleur pari est de créer un tableau sur un répertoire différent et il suffit de copier les fichiers que vous souhaitez interroger.