2013-03-26 5 views
3

У меня есть таблица game_log с полями id, game_id и несколькими полями varchar.Как разбить таблицу MySQL на два индекса

id является основным ключом, а game_id является уникальным ключом.

Там вы два частые запросы:

SELECT * FROM game_log ORDER BY id DESC LIMIT 20 
SELECT * FROM game_log WHERE game_id = <value> ORDER BY id DESC 

Стол огромные (6.1GB и 32M строк). InnoDB. Строки в нем добавляются случайным образом (по одному на запрос). Кроме того, некоторые игры удаляются.

Мне нужно уменьшить чувствительность ввода-вывода IO и imrpove.

Должен ли я использовать key или range перегородки? Если range, то по id или по game_id? Есть ли какая-то теория?

+0

Использование разделов, убедитесь, что каждый раздел помещается в 'innodb_buffer_pool_size', чтобы избежать ввода/вывода ПЕЙДЖИНГ я –

ответ

4

Использовать разделение по диапазону.

Если вы разделяете ключ, оба ваших примера запроса должны касаться каждого раздела.

Теория состоит в том, что разбиение на разделы с помощью KEY подобно разбиению на разделы по хэшу, поскольку последовательные значения первичного ключа привязываются к отдельным разделам. Запросив ряд значений id, вы испортите обрезку раздела.

Демо:

CREATE TABLE `game_log` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `game_id` int(11) NOT NULL DEFAULT '0', 
    `xyz` varchar(15) DEFAULT NULL, 
    PRIMARY KEY (`id`,`game_id`) 
) 
PARTITION BY KEY() 
PARTITIONS 13; 

INSERT INTO game_log (game_id) VALUES (1), (2), (3), (4), (5), (6); 

EXPLAIN PARTITIONS SELECT * FROM game_log ORDER BY id DESC LIMIT 3\G 
      id: 1 
    select_type: SIMPLE 
     table: game_log 
    partitions: p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12 

EXPLAIN PARTITIONS SELECT * FROM game_log WHERE game_id = 4 ORDER BY id DESC LIMIT 3\G 
      id: 1 
    select_type: SIMPLE 
     table: game_log 
    partitions: p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12 

Принимая во внимание, если вы разделите диапазоном на game_id, вы можете получить раздел обрезку, чтобы помочь вам, по крайней мере, когда вы запрашиваете для конкретного game_id. Но ваш запрос на любой порядок game_id по id desc по-прежнему привязан к каждому разделу.

CREATE TABLE `game_log` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `game_id` int(11) NOT NULL DEFAULT '0', 
    `xyz` varchar(15) DEFAULT NULL, 
    PRIMARY KEY (`id`,`game_id`) 
) 
PARTITION BY RANGE (game_id) 
(PARTITION p1 VALUES LESS THAN (3), 
PARTITION p2 VALUES LESS THAN (6), 
PARTITION p3 VALUES LESS THAN MAXVALUE); 

INSERT INTO game_log (game_id) VALUES (1), (2), (3), (4), (5), (6); 

EXPLAIN PARTITIONS SELECT * FROM game_log ORDER BY id DESC LIMIT 3\G 
      id: 1 
    select_type: SIMPLE 
     table: game_log 
    partitions: p1,p2,p3 

EXPLAIN PARTITIONS SELECT * FROM game_log WHERE game_id = 4 ORDER BY id DESC LIMIT 3\G 
      id: 1 
    select_type: SIMPLE 
     table: game_log 
    partitions: p2 
+0

Спасибо большое. Я думаю, что я также могу добавить 'game_id> [некоторый идентификатор игры из последнего раздела]' в запросе id id DESC LIMIT. –

+0

Хмм, это выглядит странно для меня: 'PRIMARY KEY (id, game_id)', если требуется. Мне еще нужен отдельный неповторимый ключ для 'game_id'? –

+1

Да, было бы полезно иметь отдельный указатель на game_id. Попробуйте проанализировать запросы с помощью EXPLAIN, как я показал, до и после создания дополнительного индекса в game_id, и вы увидите, что он использует индекс. (Делайте это с тестовой базой данных, а не с вашей производственной системой на 6 ГБ.) –

Смежные вопросы