Para ter um índice parcial semelhante ao PostgreSQL no MySQL 5.5

9

Eu tenho big data em que seleciono apenas um pequeno intervalo de dados por vez, de modo que a seleção esteja sempre em uma sequência. Eu estou tentando implementar o PostgreSQL como índice parcial no MySQL, que é direcionado para esses fins. Não tenho certeza se a restrição exclusiva parcial é a mesma que eu quero.

Código no PostgreSQL 9.4

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

Tentativa no índice parcial do ypercube no MySQL

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

Como você pode criar um índice parcial semelhante ao PostgreSQL no MySQL 5.5 ou similar?

Léo Léopold Hertz 준영
fonte
4
O MySQL não implementou índices parciais. Você pode adicionar outra tabela em seu design que armazena apenas as linhas com is_active = TRUE(ou tem apenas uma coluna, a PK de dir_events).
ypercubeᵀᴹ

Respostas:

13

Nem o MySQL nem os irmãos (MariaDB, Drizzle, etc) implementaram índices parciais.

O que você pode fazer, com esta restrição em mente:

  • a) crie um índice simples (não parcial) (is_active, measurement_id). Será usado em consultas onde o índice parcial seria. Obviamente, se a is_activecoluna for 3% Verdadeiro e 97% falso, esse índice será muito maior (que um índice parcial). Mas ainda menor que a tabela e útil para essas consultas.
    Outra limitação é que o índice não pode estar UNIQUEcom esta solução, portanto a restrição não é imposta. Se o índice for criado com UNIQUE, a exclusividade também será aplicada para as linhas is_active = FALSE. Presumo que você não queira isso:

    CREATE INDEX dir_events
        ON events (is_active, measurement_id)
        USING btree ;
  • b1) (a variação simples de b): adicione outra tabela em seu design, com apenas as colunas da chave primária eventse uma chave estrangeira em events. Esta tabela deve ter apenas linhas em que isso is_activeé verdadeiro na tabela original (isso será imposto pelo seu aplicativo / procedimentos). Consultas com is_active = TRUEteria de ser alterado para se juntar a essa tabela (em vez do WHEREestado.)
    A UNIQUEnão é aplicada tanto com esta solução, mas as consultas só iria fazer uma junção simples (com um índice muito menor) e deve ser bastante eficiente:

    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) uma solução mais complexa: adicione outra tabela em seu design, com apenas as colunas de chave primária da tabela emeasurement_id . Como na sugestão anterior, esta tabela deve ter apenas linhas onde isso is_activeé verdade na tabela original (isso também será aplicado pelo seu aplicativo / procedimentos). Em seguida, use esta tabela apenas para consultas que tenham WHERE is_active = TRUEe precisem apenas da measurement_idcoluna. Se mais colunas forem necessárias events, será necessário join, como antes.
    A UNIQUErestrição pode ser imposta com esta solução. A duplicação da measurement_idcoluna também pode ser protegida para ser consistente (com uma restrição extra exclusiva eventse uma chave estrangeira composta):

    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) talvez o mais simples de todos: use o PostgreSQL. Tenho certeza de que existem pacotes para sua distribuição Linux. Eles podem não ser a versão mais recente do Postgres, mas foram adicionados índices parciais no 7.0 (ou anterior?), Portanto você não deve ter nenhum problema. Além disso, estou confiante de que você pode instalar a versão mais recente em praticamente qualquer distribuição Linux - mesmo com um pouco de dificuldade. Você só precisa instalá-lo uma vez.

ypercubeᵀᴹ
fonte
Ótima resposta. Segway: O wiki sobre índices parciais cita um blog "No MySQL, o termo" índice parcial "às vezes é usado para se referir a índices de prefixo", que não é declarado em nenhum lugar nos documentos do MySQL. É uma terminologia confusa cunhada nesse blog. O blog também afirma que os índices de prefixo são menores / com melhor desempenho, o que dependeria. Um prefixo de string criaria uma btree com menos profundidade e mais páginas por folha, para que as digitalizações de índice sejam mais rápidas; as buscas seriam mais lentas. Além disso, use o PostgreSQL! A primeira menção PG eu encontrei é este doc op-ed estranhamente em v7.0 postgresql.org/docs/7.0/partial-index.htm
Davos
0

Não é o ideal, mas se você tiver validação em campo, poderá fazer uma alteração que invalide o valor. Por exemplo, caracteres ilegais ou números negativos. Você pode fazer essa alteração ao excluir manualmente e sabe que não entrará em conflito com um valor válido. Você também precisa observar os valores excluídos que não estão em conflito também.

Em um caso, eu tinha uma coluna de email com uma restrição exclusiva e um ID inteiro de incremento automático para cada linha. Na exclusão suave, adicionei "id @", em que id era o ID da linha exclusivo, antes do email real. @não é permitido em e-mails, a menos que seja citado, por isso sei que nenhum e-mail válido entrará em conflito com o novo valor e, portanto, nunca entrará em conflito com um e-mail válido. O ID inteiro exclusivo também garante que cada linha excluída será exclusiva, mesmo que o mesmo email seja excluído várias vezes.

Sei que isso não é o ideal, mas é uma maneira simples de solucionar o problema.

OBSERVAÇÃO: A alteração mencionada adiciona caracteres ao campo exclusivo; portanto, tive que fazer truques adicionais se o valor atual já estiver no comprimento máximo / próximo dele. Eles são específicos de aplicativos, portanto, não vale a pena mencionar aqui, mas esteja ciente e crie uma solução alternativa para isso também. Essa é uma maneira simples de solucionar a falta do recurso de índice parcial.

Charles L.
fonte