Avere un indice parziale simile a PostgreSQL in MySQL 5.5


9

Ho grandi quantità di dati in cui seleziono solo un piccolo intervallo di dati alla volta in modo tale che la selezione sia sempre in sequenza. Sto cercando di implementare PostgreSQL come indice parziale in MySQL che è destinato a tali scopi. Non sono sicuro che il vincolo univoco parziale sia uguale a quello che desidero.

Codice in PostgreSQL 9.4

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

Tentativo di indice parziale di ypercube in MySQL

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

Come si può creare un indice parziale simile a PostgreSQL in MySQL 5.5 o simile?


4
MySQL non ha implementato indici parziali. È possibile aggiungere un'altra tabella nel disegno che memorizza solo le righe con is_active = TRUE(o ha solo una colonna, il PK di dir_events).
ypercubeᵀᴹ

Risposte:


13

Né MySQL né i fratelli (MariaDB, Drizzle, ecc.) Hanno implementato indici parziali.

Cosa puoi fare, tenendo presente questa limitazione:

  • a) crea un indice semplice (non parziale) su (is_active, measurement_id). Verrà utilizzato nelle query in cui l'indice parziale sarebbe. Ovviamente se la is_activecolonna è vera al 3% e falsa al 97%, questo indice sarà molto più grande (di un indice parziale). Ma ancora più piccolo della tabella e utile per queste query.
    Un'altra limitazione è che l'indice non può essere UNIQUEcon questa soluzione, quindi il vincolo non viene applicato. Se l'indice viene creato con UNIQUE, l'unicità verrà applicata anche per le righe is_active = FALSE. Presumo che tu non voglia che:

    CREATE INDEX dir_events
        ON events (is_active, measurement_id)
        USING btree ;
  • b1) (la semplice variazione di b): aggiungi un'altra tabella nel tuo progetto, con solo le colonne della chiave primaria eventse una chiave esterna a events. Questa tabella deve contenere solo righe in cui is_activeè vero nella tabella originale (ciò verrà applicato dall'applicazione / dalle procedure). Le query con is_active = TRUEverrebbero modificate per unirsi a quella tabella (invece che per la WHEREcondizione).
    Non UNIQUEviene applicato neanche con questa soluzione ma le query farebbero solo un semplice join (con un indice molto più piccolo) e dovrebbero essere abbastanza efficienti:

    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) una soluzione più complessa: aggiungi un'altra tabella nel tuo progetto, con solo le colonne chiave primaria della tabella emeasurement_id . Come nel suggerimento precedente, questa tabella dovrebbe contenere solo righe in cui is_activeè vero nella tabella originale (anche questa verrà applicata dall'applicazione / dalle procedure). Quindi utilizzare questa tabella solo per le query che hanno WHERE is_active = TRUEe richiedono solo la measurement_idcolonna. Se sono necessarie più colonne da events, dovrai join, come prima.
    Il UNIQUEvincolo può essere applicato con questa soluzione. La duplicazione della measurement_idcolonna può anche essere garantita per essere coerente (con un vincolo univoco aggiuntivo su eventsuna chiave esterna composita):

    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) forse il più semplice di tutti: usa PostgreSQL. Sono sicuro che ci sono pacchetti per la tua distribuzione Linux. Potrebbero non essere l'ultima versione di Postgres ma gli indici parziali sono stati aggiunti in 7.0 (o precedenti?), Quindi non dovresti avere problemi. Inoltre, sono sicuro che potresti installare l'ultima versione in quasi tutte le distribuzioni Linux, anche con un po 'di seccatura. Devi solo installarlo una volta.


Bella risposta. Segway: la wiki sugli indici parziali cita un blog "In MySQL, il termine" indice parziale "viene talvolta usato per riferirsi agli indici prefissi" che non è indicato da nessuna parte nei documenti MySQL. È una terminologia confusa coniata su quel blog. Il blog afferma inoltre che gli indici dei prefissi sono più piccoli / performanti, il che dipenderebbe. Un prefisso di stringa creerebbe un btree con meno profondità, ma più pagine per foglia, quindi le scansioni dell'indice potrebbero essere più veloci; le ricerche sarebbero più lente. Inoltre, usa PostgreSQL! La prima menzione di PG che ho trovato è questo documento stranamente pubblicato in v7.0 postgresql.org/docs/7.0/partial-index.htm
Davos

0

Non è l'ideale, ma se si dispone della convalida sul campo, è possibile apportare una modifica che rende il valore non valido. Ad esempio personaggi illegali o numeri negativi. Puoi apportare questa modifica durante l'eliminazione software e sai che non si scontrerà con un valore valido. È inoltre necessario controllare che i valori eliminati non siano in conflitto tra loro.

In 1 caso, avevo una colonna e-mail con un vincolo univoco e un ID intero con incremento automatico per ogni riga. Alla cancellazione soft, ho aggiunto "id @", dove id era l'ID riga univoco, prima dell'email reale. @non è consentito nelle e-mail a meno che non sia citato, quindi so che nessuna e-mail valida si scontrerà con il nuovo valore e quindi non si scontrerà mai con una e-mail valida. L'ID intero univoco garantisce inoltre che ogni riga eliminata sarà univoca, anche se la stessa e-mail viene eliminata più volte.

So che questo non è l'ideale, ma è un modo semplice per aggirare il problema.

NOTA: la modifica che menziono aggiunge caratteri al campo univoco, quindi ho dovuto fare ulteriori trucchi se il valore corrente è già alla / vicino alla lunghezza massima. Sono specifici dell'applicazione, quindi non vale la pena menzionare qui, ma attenzione e escogitare una soluzione anche per questo e questo è un modo semplice per aggirare la funzionalità di indice parziale.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.