Иметь PostgreSQL-подобный частичный индекс в MySQL 5.5

9

У меня есть большие данные, где я выбираю только небольшой интервал данных, чтобы выбор всегда был в последовательности. Я пытаюсь реализовать PostgreSQL как частичный индекс в MySQL, который предназначен для таких целей. Я не уверен, что частичное ограничение уникальности совпадает с тем, которое я хочу.

Код в PostgreSQL 9.4

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

Попытка частичного индекса ypercube в MySQL

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

Как вы можете создать PostgreSQL-подобный частичный индекс в MySQL 5.5 или аналогичный?

Лео Леопольд Герц 준영
источник
4
MySQL не реализовал частичные индексы. Вы можете добавить другую таблицу в свой дизайн, которая хранит только строки с is_active = TRUE(или имеет только один столбец, PK of dir_events).
ypercubeᵀᴹ

Ответы:

13

Ни MySQL, ни братья и сестры (MariaDB, Drizzle и т. Д.) Не реализовали частичные индексы.

Что вы можете сделать, учитывая это ограничение:

  • а) сделать простой (не частичный) указатель на (is_active, measurement_id). Он будет использоваться в запросах, где частичный индекс будет. Конечно, если is_activeстолбец равен 3% True и 97% false, этот индекс будет намного больше (чем частичный индекс). Но все же меньше таблицы и полезен для этих запросов.
    Другим ограничением является то, что индекс не может быть 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, как и раньше. Ограничение может быть приведено в исполнение с этим решением. Дублирование столбца также может быть гарантировано согласованным (с дополнительным уникальным ограничением и составным внешним ключом):
    UNIQUEmeasurement_idevents

    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 ;
    
  • в) может быть, самый простой из всех: использовать PostgreSQL. Я уверен, что есть пакеты для вашего дистрибутива Linux. Они могут быть не последней версией Postgres, но частичные индексы были добавлены в 7.0 (или ранее?), Поэтому у вас не должно возникнуть проблем. Кроме того, я уверен, что вы можете установить последнюю версию практически в любом дистрибутиве Linux - даже с небольшими хлопотами. Вам нужно установить его только один раз.

ypercubeᵀᴹ
источник
Отличный ответ. Segway: вики по частичным индексам цитирует блог «В MySQL термин« частичный индекс »иногда используется для ссылки на префиксные индексы», который нигде не указан в документации по MySQL. Это запутанная терминология, придуманная в этом блоге. Блог также утверждает, что префиксные индексы меньше / производительнее, что будет зависеть. Строковый префикс создаст btree с меньшей глубиной, но с большим количеством страниц на листе, поэтому сканирование индекса может быть быстрее; ищет медленнее. Также используйте PostgreSQL! Первое упоминание PG, которое я обнаружил, - это странный документ в v7.0 postgresql.org/docs/7.0/partial-index.htm
Давос,
0

Это не идеально, но если у вас есть проверка на поле, вы можете внести изменение, которое сделает значение недействительным. Например, недопустимые символы или отрицательные числа. Вы можете внести это изменение при мягком удалении, и вы знаете, что оно не будет конфликтовать с допустимым значением. Вам также нужно следить за тем, чтобы мягкие удаленные значения не конфликтовали друг с другом.

В одном случае у меня был столбец электронной почты с уникальным ограничением и целочисленным идентификатором автоинкремента для каждой строки. При мягком удалении я добавил «id @», где id был уникальным идентификатором строки перед реальным электронным письмом. @не допускается в электронных письмах, если они не указаны в кавычках, поэтому я знаю, что ни одно действительное письмо не будет конфликтовать с новым значением, и поэтому оно никогда не будет конфликтовать с действительным письмом. Уникальный целочисленный идентификатор также гарантирует, что каждая удаленная строка будет уникальной, даже если один и тот же адрес электронной почты будет удален несколько раз.

Я знаю, что это не идеально, но это простой способ обойти эту проблему.

ПРИМЕЧАНИЕ: упомянутое мной изменение добавляет символы в уникальное поле, поэтому мне пришлось делать дополнительные трюки, если текущее значение уже находится на максимальной длине или близко к ней. Они относятся к конкретному приложению, поэтому не стоит здесь упоминать, но имейте в виду и примите решение этой проблемы, и это простой способ обойти пропущенную функцию частичного индекса.

Чарльз Л.
источник