在MySQL 5.5中具有类似PostgreSQL的部分索引


9

我有大数据,一次只能选择一小段数据,因此选择总是按顺序进行的。我正在尝试针对此类目的在MySQL中实现像部分索引这样的PostgreSQL。我不确定部分唯一约束是否与我想要的约束相同。

PostgreSQL 9.4中的代码

CREATE UNIQUE INDEX dir_events
    ON events (measurement_id)
    USING btree
    (eventBody)
    WHERE is_active;

在MySQL中尝试ypercube的部分索引

CREATE UNIQUE INDEX dir_events
    [index_type] -- TODO what here?
    ON events (measurement_id, is_active)
    [index_type] -- TODO what here?

如何在MySQL 5.5或类似版本中创建类似PostgreSQL的部分索引?


4
MySQL尚未实现部分索引。您可以在设计中添加另一个表,该表仅存储带有的行is_active = TRUE(或只有一个列,即的PK dir_events)。
ypercubeᵀᴹ

Answers:


13

MySQL和兄弟姐妹(MariaDB,Drizzle等)都没有实现部分索引。

考虑到此限制,您可以做什么:

  • a)在上创建一个简单(而非部分)索引(is_active, measurement_id)。将在部分索引将用于的查询中使用。当然,如果is_active列的True为3%,False为97%,则该索引将比部分索引大得多。但是仍然小于表,对于这些查询很有用。
    另一个限制是UNIQUE该解决方案不能使用索引,因此不会强制执行约束。如果使用创建索引,则具有UNIQUE的行也将强制唯一性is_active = FALSE。我假设您不想要这样:

    CREATE INDEX dir_events
        ON events (is_active, measurement_id)
        USING btree ;
  • b1)(b的简单变体):在设计中添加另一个表,仅包含的主键列events和的外键events。该表仅应包含is_active原始表中为true的行(这将由您的应用程序/过程强制执行)。使用的查询is_active = TRUE将被更改为联接到该表(而不是WHERE条件)
    UNIQUE此解决方案都不强制使用,但是查询只会进行简单的联接(到更小的索引),并且应该非常有效:

    CREATE TABLE events_active
    ( event_id INT NOT NULL,         -- assuming an INT primary key on events
      PRIMARY KEY (event_id),
      FOREIGN KEY (event_id)
        REFERENCES events (event_id)
    ) ;
    
    INSERT INTO events_active 
      (event_id)
    SELECT event_id
    FROM events
    WHERE is_active = TRUE ;
  • b2)一个更复杂的解决方案:在您的设计中添加另一个表,其中仅包含表measurement_id的主键列。与之前的建议一样,此表应仅包含is_active原始表中true的行(这也将由您的应用程序/过程强制执行)。然后,仅将此表用于具有WHERE is_active = TRUE且仅需要该measurement_id列的查询。如果从需要更多的列events,你必须join像以前一样。
    UNIQUE约束可以使用此解决方案来执行。measurement_id列的重复也可以确保一致(带有一个额外的唯一约束events和一个复合外键):

    ALTER TABLE events
      ADD UNIQUE (event_id, measurement_id) ;
    
    CREATE TABLE events_active
    ( event_id INT NOT NULL,
      measurement_id INT NOT NULL.
      PRIMARY KEY (event_id, measurement_id),
      UNIQUE (measurement_id),
      FOREIGN KEY (event_id, measurement_id)
        REFERENCES events (event_id, measurement_id)
    ) ;
    
    INSERT INTO events_active 
      (event_id, measurement_id)
    SELECT event_id, measurement_id
    FROM events
    WHERE is_active = TRUE ;
  • c)也许是最简单的:使用PostgreSQL。我确定有适合您Linux发行版的软件包。它们可能不是Postgres的最新版本,但是在7.0(或更早的版本)中添加了部分索引,因此您应该不会有问题。另外,我相信您可以在几乎所有Linux发行版中安装最新版本-即使有一点麻烦。您只需要安装一次。


好答案。Segway:关于部分索引的Wiki引用了一个博客“在MySQL中,术语“部分索引”有时用于指代前缀索引”,这在MySQL文档中未作任何说明。那是在该博客上创造的混淆术语。该博客还声称前缀索引会更小/性能更好,这取决于。字符串前缀将创建一个深度较小的btree,但每个叶子的页数更多,因此索引扫描可能会更快。搜寻会比较慢。另外,使用PostgreSQL!我发现的第一个PG是在v7.0中这个奇怪的op-doc文档postgresql.org/docs/7.0/partial-index.htm
达沃斯

0

这并不理想,但是如果您在现场进行了验证,则可以进行更改以使该值无效。例如非法字符或负数。您可以在进行软删除时进行此更改,并且知道它不会与有效值冲突。您还需要注意软删除的值也不会相互冲突。

在一种情况下,我有一个电子邮件列,该列具有唯一约束和每行的自动递增整数id。在进行软删除时,我在真实电子邮件之前添加了“ id @”,其中id是唯一的行ID。 @除非带引号,否则不允许在电子邮件中使用,因此我知道没有有效的电子邮件会与新值冲突,因此这永远不会与有效的电子邮件发生冲突。唯一的整数ID还可以确保每条被删除的行都是唯一的,即使多次删除同一封电子邮件也是如此。

我知道这并不理想,但这是解决此问题的简单方法。

注意:我提到的更改字符添加到唯一字段,因此如果当前值已经在最大长度附近,我必须做一些额外的技巧。它们是特定于应用程序的,因此在这里不值得一提,但是请注意并为此提供解决方法,这是解决缺少部分索引功能的简单方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.