Untuk memiliki Partial Index seperti PostgreSQL di MySQL 5.5

9

Saya memiliki data besar di mana saya hanya memilih interval data kecil pada suatu waktu sehingga pemilihannya selalu berurutan. Saya mencoba menerapkan PostgreSQL seperti Partial index di MySQL yang ditargetkan untuk keperluan seperti itu. Saya tidak yakin apakah batasan unik parsial sama dengan yang saya inginkan.

Kode dalam PostgreSQL 9.4

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

Cobalah indeks parsial ypercube di MySQL

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

Bagaimana Anda bisa membuat indeks parsial mirip PostgreSQL di MySQL 5.5 atau serupa?

Léo Léopold Hertz 준영
sumber
4
MySQL belum menerapkan indeks parsial. Anda bisa menambahkan tabel lain dalam desain Anda yang hanya menyimpan baris dengan is_active = TRUE(atau hanya memiliki satu kolom, PK dir_events).
ypercubeᵀᴹ

Jawaban:

13

Baik MySQL maupun saudara kandung (MariaDB, Drizzle, dll) telah menerapkan indeks parsial.

Apa yang dapat Anda lakukan, dengan batasan ini:

  • a) membuat indeks sederhana (tidak parsial) pada (is_active, measurement_id). Ini akan digunakan dalam kueri di mana indeks parsial akan. Tentu saja jika is_activekolomnya 3% Benar dan 97% salah, indeks ini akan jauh lebih besar (dari sebagian indeks). Tetapi masih lebih kecil dari tabel dan berguna untuk pertanyaan ini.
    Keterbatasan lain adalah indeks tidak dapat UNIQUEdengan solusi ini sehingga kendala tidak ditegakkan. Jika indeks dibuat dengan UNIQUE, keunikan akan diberlakukan untuk baris is_active = FALSEjuga. Saya berasumsi Anda tidak menginginkan itu:

    CREATE INDEX dir_events
        ON events (is_active, measurement_id)
        USING btree ;
    
  • b1) (variasi sederhana b): tambahkan tabel lain dalam desain Anda, dengan hanya kolom kunci utama eventsdan kunci asing events. Tabel ini hanya boleh memiliki baris yang is_activebenar dalam tabel asli (ini akan diberlakukan oleh aplikasi / prosedur Anda). Kueri dengan is_active = TRUEakan diubah untuk bergabung ke tabel itu (alih-alih WHEREkondisi.)
    Tidak UNIQUEdiberlakukan baik dengan solusi ini tetapi kueri hanya akan melakukan gabungan sederhana (ke indeks yang jauh lebih kecil) dan harus cukup efisien:

    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) solusi yang lebih kompleks: tambahkan tabel lain dalam desain Anda, dengan hanya kolom kunci utama dari tabel danmeasurement_id . Seperti pada saran sebelumnya, tabel ini seharusnya hanya memiliki baris-baris yang is_activebenar dalam tabel asli (ini akan diberlakukan juga oleh aplikasi / prosedur Anda). Kemudian gunakan tabel ini sebagai gantinya untuk kueri yang memiliki WHERE is_active = TRUEdan hanya membutuhkan measurement_idkolom. Jika diperlukan lebih banyak kolom events, Anda harus join, seperti sebelumnya.
    The UNIQUEkendala dapat ditegakkan dengan solusi ini. Duplikasi measurement_idkolom juga dapat dijamin konsisten (dengan batasan unik ekstra eventsdan kunci asing gabungan):

    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) mungkin yang paling sederhana: gunakan PostgreSQL. Saya yakin ada paket untuk distribusi Linux Anda. Itu mungkin bukan versi terbaru dari Postgres tetapi indeks parsial ditambahkan pada 7.0 (atau lebih awal?) Sehingga Anda seharusnya tidak memiliki masalah. Plus, saya yakin Anda dapat menginstal versi terbaru di hampir semua distribusi Linux - bahkan dengan sedikit kerumitan. Anda hanya perlu menginstalnya sekali.

ypercubeᵀᴹ
sumber
Jawaban yang bagus Segway: Wiki pada indeks parsial mengutip blog "Di MySQL, istilah" indeks parsial "kadang-kadang digunakan untuk merujuk pada indeks awalan" yang dinyatakan di mana saja dalam dokumen MySQL. Ini membingungkan terminologi yang diciptakan di blog itu. Blog juga mengklaim bahwa indeks awalan lebih kecil / performan, yang tergantung. Awalan string akan membuat btree dengan kedalaman lebih sedikit, namun lebih banyak halaman per daun, jadi pemindaian indeks mungkin lebih cepat; berusaha akan lebih lambat. Juga, gunakan PostgreSQL! Penyebutan PG pertama yang saya temukan adalah doc op-ed aneh ini di v7.0 postgresql.org/docs/7.0/partial-index.htm
Davos
0

Ini tidak ideal, tetapi jika Anda memiliki validasi di lapangan, Anda bisa membuat perubahan yang membuat nilai tidak valid. Misalnya karakter ilegal, atau angka negatif. Anda dapat melakukan perubahan ini saat menghapus lunak dan Anda tahu itu tidak akan berbenturan dengan nilai yang valid. Anda juga perlu memperhatikan nilai-nilai lunak yang dihapus tidak saling bertabrakan juga.

Dalam 1 kasus, saya memiliki kolom email dengan kendala unik dan id integer autoincrement untuk setiap baris. Pada penghapusan lunak, saya menambahkan "id @", di mana id adalah ID baris unik, sebelum email yang sebenarnya. @tidak diperbolehkan dalam email kecuali dikutip, jadi saya tahu tidak ada email yang valid akan berbenturan dengan nilai baru, dan jadi ini tidak akan pernah berbenturan dengan email yang valid. ID integer unik juga menjamin setiap baris yang dihapus akan unik, bahkan jika email yang sama dihapus beberapa kali.

Saya tahu ini tidak ideal, tetapi ini adalah cara sederhana untuk mengatasi masalah ini.

CATATAN: Perubahan yang saya sebutkan menambahkan karakter ke bidang unik, jadi saya harus melakukan trik tambahan jika nilai saat ini sudah di / dekat panjang maks. Mereka adalah aplikasi spesifik, jadi tidak layak disebutkan di sini, tetapi berhati-hatilah dan mencari solusi untuk itu juga dan ini adalah cara sederhana untuk mengatasi kehilangan sebagian fitur indeks.

Charles L.
sumber