Eu tenho a seguinte tabela :
CREATE TABLE `twitter_relationships` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`source_twitter_id` bigint(20) NOT NULL,
`target_twitter_id` bigint(20) NOT NULL,
`relationship_status` tinyint(1) NOT NULL,
`status_change_date` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`,`user_id`),
UNIQUE KEY `source_and_target` (`user_id`,`source_twitter_id`,`target_twitter_id`),
KEY `target_status_and_change_date_index` (`user_id`,`target_twitter_id`,`relationship_status`,`status_change_date`),
KEY `user_id_index` (`user_id`,`status_change_date`)
) ENGINE=InnoDB AUTO_INCREMENT=116597775 DEFAULT CHARSET=latin1
/*!50100 PARTITION BY HASH (user_id)
PARTITIONS 1000 */
Esta tabela é bem grande, aproximadamente 150 milhões de registros.
E tenho a seguinte consulta:
SELECT target_twitter_id
FROM `twitter_relationships`
WHERE (`twitter_relationships`.`relationship_status` = ?
AND `twitter_relationships`.`user_id` = ?
AND `twitter_relationships`.`source_twitter_id` = ?)
LIMIT ?, ?
Aqui está a explicação para esta consulta :
id: 1
select_type: SIMPLE
table: twitter_relationships
type: ref
possible_keys: source_and_target,target_status_and_change_date_index,user_id_index
key: source_and_target
key_len: 12
ref: const,const
rows: 8560582
Extra: Using where
Alguma ideia do que posso fazer na consulta ou mesmo na estrutura da tabela para agilizar essa consulta?
Primeiro, como você já tem um índice UNIQUE que contém o
user_id
, você deve conseguir se livrar doid
campo e usar o índice UNIQUE como PRIMARY KEY:Infelizmente, embora isso remova um índice, pode aumentar os requisitos de armazenamento devido à maneira como o InnoDB indexa os dados. Consulte "Como os índices secundários se relacionam com o índice agrupado" em http://dev.mysql.com/doc/refman/5.6/en/innodb-table-and-index.html
Em segundo lugar, enquanto o
source_and_target
índice tem dois dos três campos em sua cláusula WHERE, o MySQL terá que fazer uma leitura adicional para encontrar o arquivorelationship_status
.Portanto, para melhorar o desempenho, crie um índice que inclua todos os três campos em sua cláusula WHERE:
Então, se o MySQL não usar esse índice automaticamente, você pode forçar o uso dele, com:
Por fim, falta o
UNSIGNED
atributo nos camposid
,user_id
,source_twitter_id
e .target_twitter_id
Suponho que esses campos nunca armazenarão valores negativos, portanto, faria sentido torná-losUNSIGNED
.Acho que a resposta para sua consulta está aqui - https://stackoverflow.com/questions/1823685/when-should-i-use-a-composite-index
Pelo que me lembro, a ordem é importante na indexação e sua consulta tem
where status, user_id, source_twitter_id
. Você pode alterar a ordem da consulta para usar o índicesource_and_target
.espero que isto ajude!