Есть таблица с 40+ млн записей, и для быстродействия возникла необходимость ее партицировать по дате. Партицирование требует PRIMARY ключ на поле, по которому будем разбивать таблицу, поэтому PRIMARY получился по полям (id, date), потому что в таблицу очень часто вставляются записи, и поле date может дублироваться. В итоге получилась таблица вида
CREATE TABLE `orders` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
`date` int(11)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `orders` ADD PRIMARY KEY (`id`, `date`);
ALTER TABLE `orders` MODIFY `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT;
Далее создаем партиции
ALTER TABLE `orders`
PARTITION BY RANGE (`date`) PARTITIONS 6 (
PARTITION p0 VALUES LESS THAN (1420059600) ENGINE = InnoDB COMMENT = '< 01.01.2015',
PARTITION p1 VALUES LESS THAN (1483218000) ENGINE = InnoDB COMMENT = '< 01.01.2017',
PARTITION p2 VALUES LESS THAN (1496264400) ENGINE = InnoDB COMMENT = '< 01.06.2017',
PARTITION p3 VALUES LESS THAN (1514764800) ENGINE = InnoDB COMMENT = '< 01.01.2018',
PARTITION p4 VALUES LESS THAN (1527811200) ENGINE = InnoDB COMMENT = '< 01.06.2018',
PARTITION p5 VALUES LESS THAN MAXVALUE ENGINE = InnoDB COMMENT = 'Current part')
Получается, что у нас составной PRIMARY. И если выполнить запрос
SELECT * FROM `orders` WHERE `id`=1 AND `date` = UNIX_TIMESTAMP();
то задействуется составной PRIMARY и выборка будет максимально быстрой. А если сделать
SELECT * FROM `orders` WHERE `id`=1;
или
SELECT * FROM `orders` WHERE `date` = UNIX_TIMESTAMP();
то произойдет фулл скан таблицы (согласно этой статье)
Правильно ли будет создать обычные индексы на поля id и date, чтобы делать выборку только по ним
ALTER TABLE `orders`
ADD PRIMARY KEY (`id`, `date`),
ADD KEY `id` (`id`),
ADD KEY `date` (`date`);
Или составной PRIMARY работает как-то иначе, чем обычный составной ключ?
Сборка персонального компьютера от Artline: умный выбор для современных пользователей