O particionamento por intervalo divide uma tabela ou índice em segmentos com base em valores limite. Essa é a abordagem padrão para dados de séries temporais e tabelas grandes que exigem rotação regular de dados, pois permite ao otimizador de consultas ignorar completamente os segmentos irrelevantes e possibilita adicionar ou remover dados no nível da partição, em vez de linha por linha.
Cenários indicados para particionamento por intervalo
Acelere consultas de intervalo com pruning de partições
Se tabelas grandes sofrem consultas frequentes por data ou intervalo numérico — como uma tabela de pedidos (ORDER) ou um cronograma de compras (LINEITEM) — o particionamento por intervalo permite ao otimizador de consultas ignorar totalmente as partições irrelevantes. Essa técnica chama-se pruning de partições.
Por exemplo, ao particionar uma tabela de pedidos por ano e consultar dados de um único ano, o otimizador acessa apenas uma partição em vez de varrer todas. Em uma tabela com oito anos de dados, uma consulta referente a um único ano toca apenas uma das oito partições, reduzindo proporcionalmente o I/O e o tempo de varredura.
Simplifique a rotação de dados com janelas deslizantes
Para manter uma janela de dados contínua — por exemplo, conservando os últimos 36 meses de informações — o particionamento por intervalo é a estratégia mais adequada. Adicionar um novo mês e descartar o mais antigo ocorre no nível da partição, não no nível da linha:
Carregue os dados do novo mês em uma tabela de staging.
Limpe e indexe a tabela de staging.
Execute
EXCHANGE PARTITIONpara trocar a tabela de staging pela partição correspondente na tabela particionada. A tabela particionada permanece disponível para consultas durante todo o processo.Execute
DROP PARTITIONpara remover a partição do mês mais antigo.
Operar sobre partições inteiras é muito mais eficiente do que excluir linhas individuais ou reconstruir índices em toda a tabela.
Divida tabelas grandes para facilitar a gestão
Operações de backup e restauração em uma única tabela grande podem ultrapassar as janelas de manutenção disponíveis. O particionamento por intervalo divide a tabela em blocos lógicos menores, permitindo fazer backup, restaurar ou arquivar partições individuais de forma independente.
Exemplo de particionamento por intervalo
O exemplo abaixo apresenta uma tabela orders que abrange mais de nove anos. A tabela está particionada pela coluna o_orderdate em oito partições anuais (além de uma partição de overflow). Esse layout suporta tanto análises de vendas de curto intervalo por meio de pruning de partições quanto o gerenciamento de dados com janelas deslizantes.
CREATE TABLE `orders` (
`o_orderkey` int(11) NOT NULL,
`o_custkey` int(11) NOT NULL,
`o_orderstatus` char(1) DEFAULT NULL,
`o_totalprice` decimal(10,2) DEFAULT NULL,
`o_orderDATE` date NOT NULL,
`o_orderpriority` char(15) DEFAULT NULL,
`o_clerk` char(15) DEFAULT NULL,
`o_shippriority` int(11) DEFAULT NULL,
`o_comment` varchar(79) DEFAULT NULL,
PRIMARY KEY (`o_orderkey`,`o_orderDATE`,`o_custkey`),
KEY `o_orderkey` (`o_orderkey`),
KEY `i_o_custkey` (`o_custkey`),
KEY `i_o_orderdate` (`o_orderDATE`)
) ENGINE=InnoDB
PARTITION BY RANGE (TO_DAYS(o_orderdate))
(PARTITION item1 VALUES LESS THAN (TO_DAYS('1992-01-01')),
PARTITION item2 VALUES LESS THAN (TO_DAYS('1993-01-01')),
PARTITION item3 VALUES LESS THAN (TO_DAYS('1994-01-01')),
PARTITION item4 VALUES LESS THAN (TO_DAYS('1995-01-01')),
PARTITION item5 VALUES LESS THAN (TO_DAYS('1996-01-01')),
PARTITION item6 VALUES LESS THAN (TO_DAYS('1997-01-01')),
PARTITION item7 VALUES LESS THAN (TO_DAYS('1998-01-01')),
PARTITION item8 VALUES LESS THAN (TO_DAYS('1999-01-01')),
PARTITION item9 VALUES LESS THAN (MAXVALUE));
Execute EXPLAIN para confirme o pruning de partições. Uma consulta com o_orderDATE = '1992-03-01' deve acessar apenas item2:
EXPLAIN SELECT * FROM orders WHERE o_orderDATE = '1992-03-01';
+----+-------------+--------+------------+------+---------------+---------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+---------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | orders | item2 | ref | i_o_orderdate | i_o_orderdate | 3 | const | 1 | 100.00 | NULL |
+----+-------------+--------+------------+------+---------------+---------------+---------+-------+------+----------+-------+
Devido às limitações do tipo RANGE, a instrução DDL original pode não ser exibida após o particionamento da tabela comTO_DAYS()e a execução da instruçãoSHOW CREATE TABLE. Os limites das partições podem aparecer como valores inteiros de dias em vez de strings de data. Trata-se de uma limitação conhecida de exibição que não afeta o comportamento das consultas.
SHOW CREATE TABLE orders;
CREATE TABLE `orders` (
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50100 PARTITION BY RANGE (to_days(`o_orderDATE`))
(PARTITION item1 VALUES LESS THAN (727563),
PARTITION item2 VALUES LESS THAN (727929),
PARTITION item3 VALUES LESS THAN (728294),
PARTITION item4 VALUES LESS THAN (728659),
PARTITION item5 VALUES LESS THAN (729024),
PARTITION item6 VALUES LESS THAN (729390),
PARTITION item7 VALUES LESS THAN (729755),
PARTITION item8 VALUES LESS THAN (730120),
PARTITION item9 VALUES LESS THAN MAXVALUE) */
Particionamento por colunas de intervalo
O particionamento por colunas de intervalo estende o particionamento por intervalo de três formas:
Apenas nomes de colunas:
RANGE COLUMNS()aceita nomes de colunas, não expressões.Suporte a múltiplas colunas:
RANGE COLUMNS()pode incluir uma ou mais colunas. A definição da partição ocorre por comparação de tuplas, e não por comparação de valores escalares.Maior variedade de tipos: As colunas-chave de partição podem ser dos tipos INTEGER, STRING, DATE ou DATETIME.
CREATE TABLE `orders` (
`o_orderkey` int(11) NOT NULL,
`o_custkey` int(11) NOT NULL,
`o_orderstatus` char(1) DEFAULT NULL,
`o_totalprice` decimal(10,2) DEFAULT NULL,
`o_orderDATE` date NOT NULL,
`o_orderpriority` char(15) DEFAULT NULL,
`o_clerk` char(15) DEFAULT NULL,
`o_shippriority` int(11) DEFAULT NULL,
`o_comment` varchar(79) DEFAULT NULL,
PRIMARY KEY (`o_orderkey`,`o_orderDATE`,`o_custkey`),
KEY `o_orderkey` (`o_orderkey`),
KEY `i_o_custkey` (`o_custkey`),
KEY `i_o_orderdate` (`o_orderDATE`)
) ENGINE=InnoDB
PARTITION BY RANGE COLUMNS(o_orderdate)
(PARTITION item1 VALUES LESS THAN ('1992-01-01'),
PARTITION item2 VALUES LESS THAN ('1993-01-01'),
PARTITION item3 VALUES LESS THAN ('1994-01-01'),
PARTITION item4 VALUES LESS THAN ('1995-01-01'),
PARTITION item5 VALUES LESS THAN ('1996-01-01'),
PARTITION item6 VALUES LESS THAN ('1997-01-01'),
PARTITION item7 VALUES LESS THAN ('1998-01-01'),
PARTITION item8 VALUES LESS THAN ('1999-01-01'),
PARTITION item9 VALUES LESS THAN (MAXVALUE));