mySQL KEY Partitioning с использованием трех полей таблицы (столбцов) - PullRequest
0 голосов
/ 21 декабря 2009

Я пишу хранилище данных, используя MySQL в качестве сервера. Мне нужно разделить таблицу на основе двух целочисленных идентификаторов и строки имени. Я прочитал (частично) документацию mySQL, касающуюся разбиения, и, кажется, наиболее подходящей схемой разделения в этом сценарии будет разделение HASH или KEY.

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

Я включил ниже фрагмент схемы таблицы, которую я хотел бы разделить на основе КОМПОЗИТА следующих полей:

идентификатор школы, идентификатор_курса, ssname (фамилия ученика).

Кстати, прежде чем кто-либо скажет, что это не лучший способ хранения информации, связанной со школой, я должен указать, что я использую только приведенный ниже случай в качестве аналогии с тем, что я пытаюсь смоделировать.

Мой текущий оператор CREATE TABLE выглядит так:

CREATE TABLE foobar (
    id         int UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
    school_id  int UNSIGNED NOT NULL,
    course_id  int UNSIGNED NOT NULL,
    ssname     varchar(64) NOT NULL,

    /* some other fields */

    FOREIGN KEY (school_id) REFERENCES school(id) ON DELETE RESTRICT ON UPDATE CASCADE,

    FOREIGN KEY (course_id) REFERENCES course(id) ON DELETE RESTRICT ON UPDATE CASCADE,

    INDEX idx_fb_si (school_id),
    INDEX idx_fb_ci (course_id),
    CONSTRAINT UNIQUE INDEX idx_fb_scs (school_id,course_id,ssname(16))
) ENGINE=innodb;

Я хотел бы знать, как изменить приведенное выше утверждение так, чтобы таблица была разделена с использованием трех полей, которые я упомянул в начале этого вопроса (а именно - school_id, course_id и начальная буква фамилии студентов).

Еще один вопрос, который я хотел бы задать:

Что произойдет в «крайних» ситуациях, например, если я попытаюсь вставить запись, содержащую действительные * school_id, course_id или фамилию, для которой не существует файла базовой многораздельной таблицы, mySQL автоматически создаст базовый файл .?

Показательный пример. У меня есть следующие школы: New York Kindergaten, Belfast Elementary и следующие курсы: алгебра Ли в Infitesmal Dimensions, запутанные сущности

Также предположим, что у меня есть следующие студенты (фамилии): Буш, Блэр, Хуссейн

Когда я добавляю новую школу (или курс, или ученика), могу ли я вставить их в таблицу foobar (на самом деле, я не могу думать, почему нет). Причина, по которой я спрашиваю, заключается в том, что я предпочитаю добавлять больше школ, курсов и т. Д., Что означает, что mySQL придется создавать дополнительные таблицы за кулисами (поскольку хеш будет генерировать новые ключи).

Буду признателен, если кто-то, имеющий опыт работы в этой области, может подтвердить (желательно со ссылками, подтверждающими их утверждение), что мое понимание (т. Е. Ручное администрирование не требуется, если я добавляю новые школы, курсы или учащихся в базу данных), правильный.

Я не знаю, был ли мой второй вопрос правильно сформулирован (ясен) или нет. Если нет, я буду рад уточнить далее.

* VALID - под действительным я имею в виду, что он действителен с точки зрения нарушения ссылочной целостности.

1 Ответ

2 голосов
/ 21 декабря 2009

Я сомневаюсь, что разбиение так же полезно, как вы думаете. Тем не менее, есть несколько других проблем с тем, что вы запрашиваете (обратите внимание: весь этот ответ относится к MySQL 5; версия 6 может отличаться):

  • столбцы, используемые при разбиении KEY, должны быть частью первичного ключа. school_id, course_id и ssname не являются частью первичного ключа.
  • в более общем смысле каждый УНИКАЛЬНЫЙ ключ (включая первичный ключ) должен включать все столбцы в разделе 1 . Это означает, что вы можете разделять только на пересечении столбцов в уникальных ключей. В вашем примере пересечение пусто.
  • Для большинства схем разделения (кроме KEY) требуются целые или нулевые значения. Если не NULL, ssname не будет целочисленным значением.
  • внешние ключи и разбиение не поддерживаются одновременно 2 . Это сильный аргумент не использовать разбиение.

К счастью, хэширование без столкновений - это то, о чем вам не нужно беспокоиться, потому что разбиение приведет к коллизиям (в противном случае в каждом разделе будет только одна строка). Если вы можете игнорировать вышеуказанные проблемы, а также ограничения для функций, используемых в выражениях секционирования , вы можете создать раздел HASH с помощью:

CREATE TABLE foobar (
    ...
) ENGINE=innodb
  PARTITION BY HASH (school_id + course_id + ORD(ssname))
  PARTITIONS 2
;

Что должно работать:

CREATE TABLE foobar (
    id         int UNSIGNED NOT NULL AUTO_INCREMENT,
    school_id  int UNSIGNED NOT NULL,
    course_id  int UNSIGNED NOT NULL,
    ssname     varchar(64) NOT NULL,

    /* some other fields */

    PRIMARY KEY (id, school_id, course_id),
    INDEX idx_fb_si (school_id),
    INDEX idx_fb_ci (course_id),
    CONSTRAINT UNIQUE INDEX idx_fb_scs (school_id,course_id,ssname)
) ENGINE=innodb
      PARTITION BY HASH (school_id + course_id)
      PARTITIONS 2
;

или

CREATE TABLE foobar (
    id         int UNSIGNED NOT NULL AUTO_INCREMENT,
    school_id  int UNSIGNED NOT NULL,
    course_id  int UNSIGNED NOT NULL,
    ssname     varchar(64) NOT NULL,

    /* some other fields */

    PRIMARY KEY (id, school_id, course_id, ssname),
    INDEX idx_fb_si (school_id),
    INDEX idx_fb_ci (course_id),
    CONSTRAINT UNIQUE INDEX idx_fb_scs (school_id,course_id,ssname)
) ENGINE=innodb
      PARTITION BY KEY (school_id, course_id, ssname)
      PARTITIONS 2
;

Что касается файлов, в которых хранятся таблицы, MySOL создаст их, хотя это может быть сделано, когда вы определяете таблицу, а не когда в нее вставляются строки. Вам не нужно беспокоиться о том, как MySQL управляет файлами. Помните, что существует ограниченное количество разделов, определяемых при создании таблицы с помощью предложения PARTITIONS *n*.

...