【问题标题】:Amazon RedShift: Unique Column not being honoredAmazon RedShift:唯一列未受尊重
【发布时间】:2013-07-19 04:06:24
【问题描述】:

我使用以下查询来创建我的表。

create table t1 (url varchar(250) unique);

然后我插入大约 500 个网址,两次。我希望第二次获得的 URL 没有新条目出现在我的表中,而是我的计数值加倍:

select count(*) from t1;

我想要的是,当我尝试添加一个已经在我的表中的 url 时,它会被跳过。 我是否在我的表减速中声明了不正确的内容?

我正在使用 AWS 的 RedShift。

样本

urlenrich=# insert into seed(url, source) select 'http://www.google.com', '1';
INSERT 0 1
urlenrich=# select * from seed;
          url          | wascrawled | source | date_crawled 
-----------------------+------------+--------+--------------
 http://www.google.com |          0 |      1 | 
(1 row)

urlenrich=# insert into seed(url, source) select 'http://www.google.com', '1';
INSERT 0 1
urlenrich=# select * from seed;
          url          | wascrawled | source | date_crawled 
-----------------------+------------+--------+--------------
 http://www.google.com |          0 |      1 | 
 http://www.google.com |          0 |      1 | 
(2 rows)

\d 种子的输出

urlenrich=# \d 种子

                  Table "public.seed"
    Column    |            Type             | Modifiers 
--------------+-----------------------------+-----------
 url          | character varying(250)      | 
 wascrawled   | integer                     | default 0
 source       | integer                     | not null
 date_crawled | timestamp without time zone | 
Indexes:
    "seed_url_key" UNIQUE, btree (url)

【问题讨论】:

  • 我对无法复制这种行为并不感到惊讶。什么版本的 PostgreSQL? select count(*) from t1; 返回什么?你用的是什么接口? (pgAdminIII、psql 等)有多少行是 NULL? (您可以在声明为 UNIQUE 的列中插入多个 NULL 值。将其声明为 PRIMARY KEY 可能是一个更好的主意。)
  • 一些证明唯一性违规的示例数据怎么样?甚至可能是 sqlfiddle.com 演示。
  • 如果你insert into seed(url,source) values('http://www.google.com',1); 两次,它会做同样的事情吗?
  • \d seed 的输出是什么?
  • @MikeSherrill'Catcall' 尝试了 PRIMARY KEY,仍然没有

标签: amazon-web-services amazon-redshift


【解决方案1】:

发现问题

Amazon RedShift 不强制执行约束...

如此处所述 http://docs.aws.amazon.com/redshift/latest/dg/t_Defining_constraints.html

他们说他们可能会在某个时候改变它。

2013 年 11 月 21 日新 RDS 增加了对 PostGres 的支持,如果您需要唯一的并且这样的 postgres rds 实例现在是最好的选择。

【讨论】:

  • 我不认为他们会在强制执行唯一约束/主键/外键时立即添加它,这将迫使他们持有一个索引,包括受键干扰的键(非常类似于分区全局索引在 Oracle 中) - 从而在插入中产生巨大的开销。我们只是确保源数据/ETL 过程中的密钥正常
【解决方案2】:

在 redshift 中,建议使用约束但不会生效,约束只会帮助查询规划器选择更好的方式来执行查询。

通常,列式数据库不管理索引或约束。

【讨论】:

    【解决方案3】:

    虽然 Amazon Redshift 不支持唯一约束,但有一些方法可以删除重复的记录,这会很有帮助。 详情见以下链接。

    copy data from Amazon s3 to Red Shift and avoid duplicate rows

    【讨论】:

    • RDS 现在支持 postgres,因此如果您需要 postgres 数据库,您不再需要使用 RedShift。
    【解决方案4】:

    在分布式系统中执行主键和唯一键很困难,更不用说列存储系统了。 RedShift (Paracel) 和 Vertica 都面临同样的问题。

    列存储的挑战在于,被问到的问题是“这个表行在另一个表行中是否有相关条目”,但列存储不是为行操作而设计的。

    在 HP Vertica 中有一个明确的命令来报告约束违规。 在 Redshift 中,您似乎必须自己动手。

        SELECT COUNT(*) AS TotalRecords, COUNT(DISTINCT {your PK_Column}) AS UniqueRecords
        FROM {Your table}
        HAVING COUNT(*)> COUNT(DISTINCT {your PK_Column}) 
    

    显然,如果你有一个多列 PK,你必须做一些更重量级的事情。

    SELECT COUNT(*)
    FROM (
        SELECT {PkColumns}
        FROM {Your Table}
        GROUP BY {PKColumns}
        HAVING COUNT(*)>1
    
    ) AS DT
    

    如果上面返回的值大于零,则说明主键违规。

    【讨论】:

      【解决方案5】:

      对于任何人:

      • 需要使用红移
      • 希望在单个查询中插入唯一的
      • 不太关心查询性能
      • 只真正关心一次插入一个唯一值

      这里有一个简单的方法来完成它

      INSERT INTO MY_TABLE (MY_COLUMNS) 
          SELECT MY_UNIQUE_VALUE WHERE MY_UNIQUE_VALUE NOT IN (
              SELECT MY_UNIQUE_VALUE FROM MY_TABLE 
              WHERE MY_UNIQUE_COLUMN = MY_UNIQUE_VALUE
          )
      

      【讨论】:

      • Redshift 不适合在这个庄园使用。 Redshift 应该只用于批量加载,并且在删除任何数据时都需要重复。这都应该作为后期处理的一部分来完成。 (自从我问这个问题以来学到了很多)
      • 只要您使用 COPY 进行批量加载,使用此方法为低命中、低行模式加载数据不会对您在 Redshift 上的性能产生负面影响。这不是试图将 Redshift 变成 Postgres,使用这种方法是有正当理由的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-18
      • 1970-01-01
      • 2016-01-12
      • 2016-07-19
      • 2020-02-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多