magento db

Prove prove prove …

Quante prove si fanno durante lo staging di una nuova istanza di uno store Magento ? Specialmente durante le attività di data-migration i test di caricamento dei dati (prodotti / categorie / clienti /coupon ecc.) si fanno (si dovrebbero fare) numerosissimi test.

Alla fine, quando siamo pronti al deploy o allo switch over, svuotiamo il db dai dati di test e siamo pronti ad iniziare l’inserimento dei dati “di produzione”. Rimane però una piccolissima annoyance che ha un impatto di immagine e, seppure in misura infinitesimale, anche sulle performance.

Che problema ? Che per esempio il primo prodotto che carichiamo avrà id 15674 invece di 1

Non sarebbe bello consegnare al nostro cliente un’istanza con tutti i contatori che partono da 1 ?

Gli auto_increment id nel db MySql (o Percona o MariaDb)

Per ogni nuovo record che Magento scrive nel db sottostante viene utilizzata (quasi ovunque nello schema) come chiave primaria della tabella un campo di tipo auto_increment: ovvero un campo che vede il proprio valore incrementato di 1 (in alcune configurazioni il valore di incremento potrebbe anche essere diverso) rispetto all’ultimo valore utilizzato. Questo garantisce che due record non possano avere la stessa chiave primaria. Ma cosa succede quando elimino un record ? Nulla: il valore dell’auto_increment è stato ormai valorizzato e continuerà ad aumentare. Quindi se ho inserito 100 prodotti il valore dell’auto_increment è ormai arrivato a 100 e anche se cancello tutti i prodotti dal db il prossimo che viene inserito avrà come id il valore 101.

Impatti sulle performance

Anche se di entità davvero infinitesimale c’è comunque un impatto sulle performance di Magento nel mantenere id “alti”. Il motivo è presto detto: la comunicazione tra php e il db avviene tramite socket TCP che inviano stringhe Sql. Il motore database riceve le stringhe, ne esegue il parsing e quindi fa il lavoro. Appare chiaro che inviare una stringa del tipo:

SELECT * FROM catalog_product_entity WHERE entity_id = 16574

è di ben 4 byte più lunga che

SELECT * FROM catalog_product_entity WHERE entity_id = 1

In un store molto trafficato con migliaia di referenze e milioni di query eseguite giornalmente si “tagliano” centinaia di megabyte di dati che trafficano da php al db. Intendiamoci: non sarà questo che risolve tutti i colli di bottiglia di Magento: ma per i puristi del fine-tuning di Magento è un plus da considerare.

Impatto sull’ immagine

Gli utenti del front-end dello store non si accorgeranno di nulla, ma il vostro cliente, che molto probabilmente opera nella console amministrativa, vi chiederà certo come mai “i numeri non partono da 1” (mi è capitato più di una volta di sentire domande del tipo: “ma ho solo 1500 prodotti, come mai arriviamo a 23578 ?”). In fondo consegnare un lavoro a regola d’arte passa anche da qui.

Come risolvere

Semplice: prima di procedere all’ultima importazione dei dati prima del deployment finale dovremmo resettare tutti gli auto_increment al valore “minimo” dei dati ancora, eventualmente, rimasti nelle tabelle. Passarsele a mano ? Nahhhh …

Ecco dunque un piccolo script che in un’unica passata resetta tutto: resetAutoIncrements.php. Mettetelo nella directory /shell della vostra istanza di magento ed eseguitelo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 
< ?php
/**
 * NOTICE OF LICENSE
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 *
 * Those who do not know how to use snail mail: The GPL is here:
 * http://www.gnu.org/licenses/gpl.html
 *
 * @category    Mage
 * @package     Mage_Shell
 * @copyright   Copyright (c) 2014 Andrea Lanfranchi (Isiweb S.r.l.)
 * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */
 
	ini_set('auto_detect_line_endings',TRUE);
	define('MAGENTO', realpath(dirname(__FILE__)));
	require_once MAGENTO.'/../app/Mage.php';
	umask(0);
	Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
 
	$dbConn = Mage::getSingleton('core/resource')->getConnection('core_write');
	$sqlStr = "SELECT table_name, column_name FROM information_schema.columns WHERE table_schema IN (select DATABASE() from dual) AND extra LIKE '%auto_increment%';";
	$resSet = $dbConn->fetchAll($sqlStr);
	$totItm = count($resSet) - 1;
 
	for ( $i = 0 ; $i < = $totItm ; $i ++ ) {
		echo 'Resetting auto-increment for ' . $resSet[$i]['table_name'] . '.' . $resSet[$i]['column_name'] . ' ... ' . PHP_EOL;
		$sqlStr = 'SELECT MAX(' . $resSet[$i]['column_name'] . ') as HigherUsedIncrement FROM ' . $resSet[$i]['table_name'] . ';';
		$resInc = $dbConn->fetchOne($sqlStr);
		$resInc = $resInc == NULL ? 0 : intval($resInc) + 1;
		$sqlStr = 'ALTER TABLE ' . $resSet[$i]['table_name'] . ' AUTO_INCREMENT = ' . $resInc . ';';
		$dbConn->query($sqlStr);
	}
 
	echo 'Done !' . PHP_EOL;
 
?>