Take the 2-minute tour ×
Magento Stack Exchange is a question and answer site for users of the Magento e-Commerce platform. It's 100% free, no registration required.

We got a server which has 5 separately shops on it. Some are practically inactive. Some are daily active. To decrease the server load. We changed the index from automatic to manual. Then we set a cronjob every 6 hours. I found enough examples of reindexing all.

We run something like this now:
Shop1: 0 0,6,12,18 * * * php -f /shell/indexer.php reindexall
Shop2: 0 1,7,13,19 * * * php -f /shell/indexer.php reindexall
and so on, to avoid overlap.

Right now the inactive shops also reindex every 6 hours where none is needed. Is there a way to only reindex what is needed with a cronjob?

Or are we doing is wrong altogether?

share|improve this question

4 Answers 4

up vote 3 down vote accepted

What you want is to create a shell cli script, and use that to determine if a index requires a re-index.

Have a look at the scripts in the shell folder (log.php will do fine) as an example on how to make such a script.

The script you create would then check the status of the index, and only re-index if it is in a status that requires indexing.

I generally create my custom shell scripts in a folder called /scripts, as I don't like to pollute the core folder shell with my custom code.

To this effect, I have a abstract class that I base all my scripts off, and it contains code that allows me to easily re-index indexers, if they require indexing.

here is my abstract class:

/**
 * Abstracted functions for scripts
 *
 * @category    ProxiBlue
 * @package     Scripts
 * @author  Lucas van Staden (sales@proxiblue.com.au)
 * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 *
 */
require_once dirname(__FILE__) . '/../shell/abstract.php';

class Mage_Shell_Scripts_Abstract extends Mage_Shell_Abstract {

    public $_doReindexFlag = false;

    public function run() {

        die('Please implement a run function inyour script');

    }
    /**
     * Get the category model
     * @return Object
     */
    public function getCatalogModel() {
        return Mage::getModel('catalog/category');
    }

    /**
     * Reindex given indexers.
     * Tests if indexer actually needs re-index, and is not in manual state before it does index.
     * 
     * @param array $reIndex 
     */
    public function reindex(array $reIndex) {

        foreach ($reIndex as $indexerId) {
            $process = $this->_getIndexer()->getProcessByCode($indexerId);
            if ($process->getStatus() == Mage_Index_Model_Process::STATUS_REQUIRE_REINDEX && $process->getMode() != Mage_Index_Model_Process::MODE_MANUAL) {
                try {
                    echo "Reindexing: " . $process->getIndexerCode();
                    $process->reindexEverything();
                } catch (Exception $e) {
                    mage::logException("{$indexer} Indexer had issues. {$e->getMessage()}");
                }
            }
        }
    }

    /**
     * Get Indexer instance
     *
     * @return Mage_Index_Model_Indexer
     */
    private function _getIndexer() {
        return Mage::getSingleton('index/indexer');
    }

    /**
     * Returns a list of cache types.
     * @return void
     */
    public function getInvalidateCache() {
        $invalidTypes = $this->_getInvalidatedTypes();
        $result = array();
        foreach($invalidTypes as $cache) {
            if ($cache->status == 1) {
                $result[] = $cache;
            }    
        }
        return $result;
    }

    /**
     * Gets a list of invalidated cache types that should be refreshed.
     * @return array Array of invalidated types.
     */
    private function _getInvalidatedTypes() {
        return Mage::getModel('core/cache')->getInvalidatedTypes();
        //return $this->_getCacheTypes();
    }

    /**
     * Gets Magento cache types.
     * @return
     */
    private function _getCacheTypes() {
        //return Mage::helper('core')->getCacheTypes();
        return Mage::getModel('core/cache')->getTypes();
    }

}

Then a class that is based off that, that calls a re-index, after some work was done.

require_once dirname(__FILE__) . '/abstract.php';

class Mage_Shell_setCategoryStatus extends Mage_Shell_Scripts_Abstract {

    public $_doReindexFlag = true;
    public function run() {

        /** code stripped out as not warrented for this answer **/

        if ($this->_doReindexFlag) {
            $this->reindex(array('catalog_product_flat',
                'catalog_category_flat',
                'catalog_category_product',
                'cataloginventory_stock',
                'catalogsearch_fulltext',
            ));
        }
    }

}

$shell = new Mage_Shell_setCategoryStatus();
$shell->run();

Hope that helps you in the right direction.

share|improve this answer
    
I have to say the answer given by @Flyingmana is in fact far smarter than my own ;) –  ProxiBlue Mar 14 at 12:26

What I know, the Index is something global, so a reindex always covers all Stores/Websites of one Magento.

But, magento has some functionality you will like. While "update on Save" does the updates to index instant, the "manual update" puts the same "updates" into a queue, which you can trigger later.

For this you will need to write an own shell script or cron job

    $pCollection = Mage::getSingleton('index/indexer')->getProcessesCollection();

    foreach ($pCollection as $process) {
        $process->indexEvents();
    }

I will not explain the basics of the process models, simple have a look at the indexEvents function, it takes the entries of the queue and updates them. But be carefull, the url Index can be a bit slow. But thats another problem.

share|improve this answer
1  
Interesting solution, I didn't know that the events are saved when "manual update" is activated. This would allow indexing only the changed data. –  Andreas von Studnitz Feb 18 at 21:29

To reindex the processes we require their ids.
For default magento there are 9 processes to reindex, numbered 1 to 9.

$ids = array(1,2,3,4,5,6,7,8,9);

Sometimes there are processes from our custom modules that also require reindexing We need to add those ids to our existing array of ids, To know the id of process, just hover on each process in your
admin panel-> System-> Index Management

You will get a url : admin/process/some_id/...... this id corresponds to the process

$ids = array(1,2,3,4,5,6,7,8,9,390,391,478);
foreach($ids as $id)
{
   //load each process through its id
   try
   {
      $process = Mage::getModel('index/process')->load($id);
      $process->reindexAll();
      echo "Indexing for Process ID # ".$id." Done<br />";
   }
   catch(Exception $e)
   {
      echo $e->getMessage();
   }
}
share|improve this answer
    
This doesn't answer my question how to change the cronjob. Also this reindexes everything. I only want to reindex the parts that are changed. –  janw Feb 11 at 12:37
<?php
// this loops through all indexes and processes those that say they require reindexing

include_once '../app/Mage.php';

$mageRunCode = isset ( $_SERVER ['MAGE_RUN_CODE'] ) ? $_SERVER ['MAGE_RUN_CODE'] : '';
$mageRunType = isset ( $_SERVER ['MAGE_RUN_TYPE'] ) ? $_SERVER ['MAGE_RUN_TYPE'] : 'store';

    $app = Mage::app ( $mageRunCode, $mageRunType );
    for($i=3; $i<=9; $i++){
        $process = Mage::getSingleton('index/indexer')->getProcessById($i);
        $state = $process->getStatus();
    //    echo '<pre>'.$process->getData('indexer_code').': '.htmlentities(print_r($process->getStatus(),true)).'</pre>';
        if($process->getStatus() == 'require_reindex'){
            $process->reindexEverything();
        }
    }
    ?>
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.