我使用sqoop将表格从Postgres导入到hdfs。我的表有uuid字段作为主键,我的命令sqoop如下:
sqoop import --connect 'jdbc:postgresql://localhost:5432/mydb' --username postgreuser --password 123456abcA --driver org.postgresql.Driver --table users --map-column-java id=String --target-dir /hdfs/postgre/users --as-avrodatafile --compress -m 2
但是我得到了错误:
Import failed: java.io.IOException: org.postgresql.util.PSQLException: ERROR: function min(uuid) does not exist
我尝试执行sql命令:SELECT min(id) from users
并得到了同样的错误。我该怎么办呢?我使用Postgres 9.4,hadoop 2.9.0和sqoop 1.4.7
我想赞美@ robin-salih的回答,我已经使用它并实现min for int,以构建以下代码:
CREATE OR REPLACE FUNCTION min(uuid, uuid)
RETURNS uuid AS $$
BEGIN
IF $2 IS NULL OR $1 > $2 THEN
RETURN $2;
END IF;
RETURN $1;
END;
$$ LANGUAGE plpgsql;
create aggregate min(uuid) (
sfunc = min,
stype = uuid,
combinefunc = min,
parallel = safe,
sortop = operator (<)
);
它几乎相同,但利用B树索引,所以select min(id) from tbl
工作在几毫米。
附:我不是pgsql专家,也许我的代码在某种程度上是错误的,在生产中使用前仔细检查,但我希望它正确使用索引和并行执行。我只是从示例代码中做到了,而不是深入研究PG中聚合的理论。
Postgres没有min / max uuid的内置函数,但您可以使用以下代码创建自己的函数:
CREATE OR REPLACE FUNCTION min(uuid, uuid)
RETURNS uuid AS $$
BEGIN
IF $2 IS NULL OR $1 > $2 THEN
RETURN $2;
END IF;
RETURN $1;
END;
$$ LANGUAGE plpgsql;
CREATE AGGREGATE min(uuid)
(
sfunc = min,
stype = uuid
);
我发现@ robin-salih和@ bodgan-mart提供的答案是一个很好的起点但最终是不正确的。这是一个对我有用的解决方案:
CREATE FUNCTION min_uuid(uuid, uuid)
RETURNS uuid AS $$
BEGIN
-- if they're both null, return null
IF $2 IS NULL AND $1 IS NULL THEN
RETURN NULL ;
END IF;
-- if just 1 is null, return the other
IF $2 IS NULL THEN
RETURN $1;
END IF ;
IF $1 IS NULL THEN
RETURN $2;
END IF;
-- neither are null, return the smaller one
IF $1 > $2 THEN
RETURN $2;
END IF;
RETURN $1;
END;
$$ LANGUAGE plpgsql;
create aggregate min(uuid) (
sfunc = min_uuid,
stype = uuid,
combinefunc = min_uuid,
parallel = safe,
sortop = operator (<)
);
有关详细信息,请参阅How to select minimum UUID with left outer join?上的帖子
这不是sqoop的问题。 Postgres不允许在uuid上使用min / max。每个uuid都是独一无二的,不会被认为比其他更大/更小。
要在sqoop中修复此问题,您可能需要使用其他字段作为拆分键。我使用created_At时间戳作为我的拆分键。