Na verdade, estou lutando para entender o problema aqui. Eu li em todos os lugares dizendo que UPDATE se beneficia de índices na cláusula WHERE.
No entanto, esta consulta,
UPDATE `documents` SET `read`="1" WHERE `docid` IN (<subquery>)
não parece estar usando um índice. A tabela documents
tem um índice docid
intermitente read
.
Quando faço um EXPLAIN
, vejo possible_keys = NULL
e rows = 8011008
(tabela cheia). A subconsulta usa chaves e lê as linhas apropriadas (2 linhas).
Por outro lado, esta consulta:
SELECT * FROM `documents` WHERE `docid` IN (<subquery>)
usa o índice docid
e é executado muito rapidamente. Ele lê algumas linhas a mais do que o necessário (conforme EXPLAIN
), mas totalmente aceitável.
Existe alguma explicação para isso?
Eu uso o MariaDB 10.
Como uma observação engraçada (em relação a SELECT
), se <subquery>
eu usar um UNION
, enquanto a subconsulta parece obter o número adequado de linhas, parece que a consulta primária NÃO usa o índice e faz uma verificação completa da tabela.
Se no UPDATE
eu uso JOIN
em vez de IN
, os índices são usados corretamente. Resolvi meus problemas usando JOIN
.
Para resolver a questão "UPDATE não usa INDEX, mas SELECT faz"...
Até muito recentemente, muitos
UPDATEs
eram processados por código diferente doSELECTs
. Recentemente, houve uma unificação na filial da Oracle. Acho que ainda não chegou ao MariaDB.Além disso, a construção
IN ( SELECT ... )
foi otimizada muito mal até 5.6. Novamente, o MariaDB pode ou não ter incluído algumas das melhorias 5.6/5.7 nesta área.Quase sempre é melhor se transformar
... IN ( SELECT ... )
emJOIN ... ON ...
. Isso é possível emUPDATE
; consulte "ATUALIZAÇÃO multi-tabela".Para mais discussões sobre seus casos específicos, forneça
SHOW CREATE TABLE
eEXPLAIN SELECT ...
.Não estou dizendo que a ramificação da Oracle necessariamente faz as coisas melhor; ao invés disso, poderia haver uma diferença.