Na documentação oficial:
https://devdocs.magento.com/guides/v2.3/extension-dev-guide/indexing.html
, está o seguinte:
`Allows tracking database changes for a certain entity (product, category and so on) and running change handler.
Emulates the materialized view technology for MySQL using triggers and separate materialization process (provides executing PHP code instead of SQL queries, which allows materializing multiple queries).`
MView significa Materialized View, que é um instantâneo do banco de dados em um determinado momento.
https://en.wikipedia.org/wiki/Materialized_view
Por que precisamos duplicar tabelas. Os indexadores são caros para executar, especialmente quando há tráfego nas páginas de categorias, os clientes fazem pedidos e os administradores salvam produtos. No produto salvo, o cache é invalidado (fora do tópico). No caso do indexador de ações, antes de finalizar a execução, ele envia os IDs da entidade afetados como tags de cache a serem limpos (tipo de cache de página inteira). Nas categorias Magento 2.0, os IDs dos produtos comprados são enviados. No Magento 2.1, os IDs do produto são enviados.
Existem 2 tabelas MySQL que mantêm códigos e status do indexador:
indexer_state
mview_state
mview_state
trabalha com Update by Schedule
em Admin> Sistema> Gerenciamento do Indexador
Update by Schedule
faz com que os indexadores sejam executados no cron.
Existem 3 entradas em Magento_Indexer/etc/contab.xml
:
<group id="index">
<job name="indexer_reindex_all_invalid" instance="Magento\Indexer\Cron\ReindexAllInvalid" method="execute">
<schedule>* * * * *</schedule>
</job>
<job name="indexer_update_all_views" instance="Magento\Indexer\Cron\UpdateMview" method="execute">
<schedule>* * * * *</schedule>
</job>
<job name="indexer_clean_all_changelogs" instance="Magento\Indexer\Cron\ClearChangelog" method="execute">
<schedule>0 * * * *</schedule>
</job>
</group>
indexer_reindex_all_invalid
é executado indexer_state
. Ainda há a necessidade de executar indexadores 'normais' no cron
indexer_update_all_views
é executado em mview_state
indexer_clean_all_changelogs
- limpa os registros de alterações usados por mview_state
Note-se que as tarefas de grupo cron indexador executado em um processo php separado, conforme declarado em etc/contab_groups.xml
:
<use_separate_process>1</use_separate_process>
.
As tabelas de alterações são:
[indexer name]_cl
(com o sufixo _cl
). por exemplo cataloginventory_stock_cl
. Se você tiver indexadores definidos para Update by Schedule
e salvar um produto no administrador, verá o entity_id
produto nessa tabela. É um grande círculo, estou pensando que fazer um pedido ou criar uma remessa também adicionará uma entrada aqui.
Alguém forneceu um exemplo no devdoc oficial sobre como criar novas visualizações materializadas e quais são os métodos de interface necessários (desconsidere a declaração acima sobre pedidos no snippet abaixo):
<?php
<VendorName>\Merchandizing\Model\Indexer;
class Popular implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
{
public function executeFull(); //Should take into account all placed orders in the system
public function executeList($ids); //Works with a set of placed orders (mass actions and so on)
public function executeRow($id); //Works in runtime for a single order using plugins
public function execute($ids); //Used by mview, allows you to process multiple placed orders in the "Update on schedule" mode
}
Isso fará sentido:
//public function execute($ids); Used by mview, allows you to process multiple **entities** in the "Update on schedule" mode
}
Onde o $ids
parâmetro possui os IDs de entidades das *_cl
tabelas.
Qual é o link entre a invalidação de cache e os indexadores. As páginas de categorias agora estão em cache de página inteira (cache de página inteira interno ou através do Varnish).
Existe \Magento\Indexer\Model\Processor\InvalidateCache::afterUpdateMview
:
/**
* Update indexer views
*
* @param \Magento\Indexer\Model\Processor $subject
* @return void
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterUpdateMview(\Magento\Indexer\Model\Processor $subject)
{
if ($this->moduleManager->isEnabled('Magento_PageCache')) {
$this->eventManager->dispatch('clean_cache_after_reindex', ['object' => $this->context]);
}
}
Voltar para Magento\Indexer\Cron\UpdateMview::execute()
:
/**
* Regenerate indexes for all invalid indexers
*
* @return void
*/
public function execute()
{
$this->processor->updateMview();
}
Magento\Indexer\Model\Processor::updateMview()
:
/**
* Update indexer views
*
* @return void
*/
public function updateMview()
{
$this->mviewProcessor->update('indexer');
}
Em app/etc/di.xml
existe:
<preference for="Magento\Framework\Mview\ProcessorInterface" type="Magento\Framework\Mview\Processor" />
/**
* Materialize all views by group (all views if empty)
*
* @param string $group
* @return void
*/
public function update($group = '')
{
foreach ($this->getViewsByGroup($group) as $view) {
$view->update();
}
}
Magento\Framework\Mview\ViewInterface
/**
* Materialize view by IDs in changelog
*
* @return void
* @throws \Exception
*/
public function update();
app/etc/di.xml
<preference for="Magento\Framework\Mview\ViewInterface" type="Magento\Framework\Mview\View" />
Em Magento\Framework\Mview\View::update()
existe:
$action = $this->actionFactory->get($this->getActionClass());
$this->getState()->setStatus(View\StateInterface::STATUS_WORKING)->save();
..
$action->execute($ids);
..
Se você pesquisar no vendor/
diretório, Magento\Framework\Mview\ActionInterface
encontrará, por exemplo, o seguinte:
Em \Magento\CatalogInventory\Model\Indexer
:
class Stock implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
Nesta classe há:
/**
* Execute materialization on ids entities
*
* @param int[] $ids
*
* @return void
*/
public function execute($ids)
{
$this->_productStockIndexerRows->execute($ids);
}
E parece que ele volta à classe 'normal' de indexadores 'execute` método que é usado pelo MView.
Sobre a limpeza do cache após o Stock Indexer. Quando um pedido é feito no check-out, as quantidades são subtraídas usando este observador:\Magento\CatalogInventory\Observer\SubtractQuoteInventoryObserver
$itemsForReindex = $this->stockManagement->registerProductsSale(
$items,
$quote->getStore()->getWebsiteId()
);
Além disso, outro observador aciona o indexador (mas não diretamente no Mview / Indexer por Schedule):
\Magento\CatalogInventory\Observer\ReindexQuoteInventoryObserver
if ($productIds) {
$this->stockIndexerProcessor->reindexList($productIds);
}
No caso do Mview, quando as novas quantidades forem subtraídas SubtractQuoteInventoryObserver
, o gatilho MySQL (criado para o Mview) inserirá uma linha cataloginventory_stock_cl
, marcando que uma reindexação (estoque e texto completo) precisa ser feita com os IDs de produtos adquiridos. Existem muitos gatilhos MySQL criados para o Mview. Veja todos eles com SHOW TRIGGERS;
.
Quando um produto fica fora de estoque após o checkout, você vê 2 linhas inseridas nessa tabela (o Magento economiza 2 vezes o item em estoque nesses 2 observadores).
Quando o cron executa o indexador de ações no modo Mview, os IDs de produtos afetados (em M2.1) ou de categorias (em M2.0) são enviados para o cache limpo como tags de cache. Por cache, quero dizer o tipo de cache de página inteira. Exemplo: catalog_product_99
ou outro formato de tag de cache, dependendo da versão do Magento. O mesmo quando o Mview não está ativado.
\Magento\CatalogInventory\Model\Indexer\Stock\AbstractAction::_reindexRows
...
$this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
E o Magento_PageCache possui um observador \Magento\PageCache\Observer\FlushCacheByTags
que limpará o tipo de cache de página inteira por tags. Faz isso para armazenar em cache de página inteira. O código relacionado ao verniz está em \Magento\CacheInvalidate\Observer\InvalidateVarnishObserver
.
Existe uma extensão gratuita que negará que o cache seja limpo em produtos ainda em estoque após o checkout do cliente:
https://github.com/daniel-ifrim/innovo-cache-improve
Limpeza de cache apenas em produtos fora de estoque após a introdução do checkout no Magento 2.2.x padrão. Veja \Magento\CatalogInventory\Model\Indexer\Stock\CacheCleaner
.
Eu estou pensando que a execução cron para indexador em Admin > Stores > Configuration > Advanced > System > Cron configuration options for group: index
deve ser definida para muito mais de 1 minuto.
Mview
refere-se a visualizações materializadas , que são as tabelas de índice.