Trovare (e ripulire) i duplicati in mySQL e spostare tabelle

Scritto il 13 Maggio 2008
Nella categoria Produzioni Proprie | Scrivi un commento
Tag: , ,

Oggi mi è capitato di voler spostare una tabella da un database ad un altro, entrambi sullo stesso server, perché una parte del progetto si è ingrandita e ora merita uno spazio tutto suo. Ovviamente la soluzione più semplice è esportare ed importare, ma oltre ad essere poco elegante, diventa lunga nel caso di una tabella con molti dati.

Database su foglio di calcolo

La soluzione più semplice è utilizzare la sintassi INSERT INTO, come nell’esempio

INSERT INTO `destinazione`.`dati`
SELECT *
FROM `origine`.`dati` ;

Questo copia la tabella dati dalla tabella originedestinazione. Volendo è possibile anche rinominare la tabella specificando due nomi diversi, oppure copiare solo alcune colonne della tabella. Molto importante, la tabella di destinazione deve essere già stata creata, con tutte le colonne e le chiavi necessarie.

Gestire invece i valori duplicati in una tabella è una cosa molto complessa, prima di tutto è necessario identificarli, la sintassi è questa:

SELECT nome, COUNT( nome ) AS totale FROM dati GROUP BY nome HAVING totale >1;

Questo identificherà tutti i nomi doppi nella dabella, solo quelli doppi, per vedere invece i valori distinti, cioè ogni singolo valore che appare, più semplicemente basta

SELECT nome, COUNT( nome ) AS totale FROM dati GROUP BY nome;

Se neanche interessa sapere quante volte appaiono, allora la query si riduce a

SELECT nome FROM dati GROUP BY nome;

Ora, eliminarli non è una cosa semplice, perché è difficile capire quali vanno tenuti e quali no, insomma non è un’azione da fare a cuor leggero e va sempre studiata. La soluzione più corretta è introdurre un vincolo di unicità sulla tabella, o come chiave o come valore unico.

ALTER INGORE TABLE `dati` ADD UNIQUE KEY ( `nome` , `numero` )

Questo comando di alterazione, aggiunge un vincolo di unicità della coppia nome,numero la clausola IGNORE permette di ignorare l’errore di duplicazione, senza la query non avrebbe successo in una tabella che non rispetta il vincolo. Non si hanno però certezze di quali altri dati vengano mantenuti.

Se l’obbiettivo è fare una pulizia assennata, il mio consiglio è procedere per passi, (prima di tutto lavorando su un backup e non dal vivo), quindi pulendo i valori doppi con la query di cui sopra, infine aggiornando i rimanenti dati dalla tabella originale.

Consigli per script PHP più veloci

Scritto il 21 Aprile 2008
Nella categoria Guide, PHP | 1 commento
Tag: , ,

Oggi ho letto il post di antirez su cosa era e invece cosa è importante ora per la programmazione, quando si fa moltissimo scripting in PHP ad esempio, e pochissima “vera” programmazione in C o simili. In particolare è diventato più utile ottimizzare in modo anche “sporco” le righe di codice, piuttosto che sapere qual’è l’algoritmo più efficiente per affrontare un problema, perché questo secondo tipo di codice è molto meno utilizzato oggi, quando spopolano le web-application.

Quindi ho deciso di prendere spunto da tre articoli che trovai tempo fa su come ottimizzare la scrittura di codice PHP, verificare, e spiegarli.

Consigli generici: meno chiamate a funzioni

Sempre, sempre, sempre, fare meno chiamate possibili alle funzioni, questa deve essere una regola generale, sempre meglio tenere in memoria una variabile in più (che poi andrà distrutta con unset). Il classico esempio non è inserire una chiamata all’interno di un ciclo, ma all’esterno oppure dentro la prima clausola di un for

for($a = 0; $a < sizeof($array); $a++)

Questo va malissimo, piuttosto meglio

$max = sizeof($array);
for($a = 0; $a < $max; $a++) {
...
}
unset($max);

Oppure più carino

for($a = 0, $max = sizeof($array); $a < $max; $a++) {
...
}
unset($max);

Consigli generici: ordine nelle condizioni

Quando si controllano più condizioni tra loro è importante farlo nell’ordine giusto e con gli operatori logici giusti.

Ad esempio usando || e && al posto dei semplici | e &, i primi hanno il vantaggio di terminare il controlla appena le condizioni non sono verificabili, quindi se controlliamo che ($var1 && $var2), se già la prima condizione è falsa, non sarà valutata la seconda facendo risparmiare tempo macchina.

Grazie a questo principio, è possibile velocizzare il codice valutando le condizioni nell’ordine giusto, cioè nel caso di una condizione ($var1 || $var2) è preferibile mettere come prima condizione quella che più spesso viene verificata.

Usare funzioni più semplici possibili

PHP mette a disposizione diverse funzioni che fanno a prima vista la stessa cosa, ma in modo diverso; ad esempio per sostituire pezzi di stringhe, ci sono ereg_replace, preg_replace e str_replace ma sono diverse tra loro, in particolare le prime due sfruttano le Espressioni Regolari, mentre la seconda cerca stringe semplici; ovviamente utilizzare quest’ultima rende il codice molto più veloce, di almeno la metà, dipende dalla complessità della RegExp.

Allo stesso modo le funzioni explode è più veloce di split, visto che anch’essa sfrutta le espressioni regolari.

Infine consiglio di utilizzare time() al posto di date('U'), in quanto la mancanza di parametri rende la prima molto più rapida e leggera.

Conta pochissimo invece utilizzare le virgolette singole 'stringa' al posto di quelle doppie "stringa", la differenza, per chi non lo sapesse, è che se una variabile appare tra due virgolette doppie viene sostituita, con le singole no; ma la differenza è talmente minima che non vale la pena di fare salti mortali per controllare tutto il codice, se scappa una virgoletta doppia (magari anche perché vogliamo inserire un codice ascii come \n), è un errore perdonabile.

Consigli che non vale la pena di seguire

Gli articoli che ho citato si perdono purtroppo anche in alcuni consigli un approssimativi o poco approfonditi, che non vale la pena di seguire.

In particolare sembra che utilizzare === al posto di == dia alcuni vantaggi, ma in realtà non è proprio così, solo in alcuni casi. Il secondo operatore infatti controlla prima che i due oggetti siano dello stesso tipo, mentre il primo cerca di converti nello stesso tipo. In particolare:

('22' == 22) è VERO
('22' === 22) è FALSO

Ho verificato che confrontando stringhe uguali, non ci sono miglioramenti sensibili scambiando == con === .

Stesso discorso per le funzioni ctype_digit e is_numeric, che tra loro sono differenti: la prima verifica se in una stringa sono scritte solo cifre, mentre la seconda controlla se un oggetto è di tipo numerico (un int, float, etc) oppure se è una stringa che rappresenta un numero, prendendo quindi per buono il valore "0.12", per cui la ctype_digit restituirebbe falso.

Mischiare un array: mix()

Scritto il 23 Aprile 2007
Nella categoria Javascript, Produzioni Proprie | Scrivi un commento
Tag: , , ,

Oggi altra funzione che potrebbe tornare utile: mix() che mischia un array in modo casuale; non mi addentro sul significato di casuale, dico soltanto che crea un array aggiungendo ogni volta un elemento preso a caso dall’array originale.

Array.prototype.mix = function() {
	var ret = new Array();
	while (this[0]) {
		ret.push(
			this.splice(
				parseInt(Math.random()*this.length),
				1)[0]
			)
	}
	while (ret[0]) {
		this.push(ret.shift());
	}
	return this;
}

La funzione oltre che mischiare l’array lo restituisce, quindi potete subito agire sul risultato di mix().

Chiaramente è applicabile anche al di fuori di un array, basta che l’oggetto supporti push, pop e splice; inoltre con pochissimi cambiamenti potete renderla una funzione esterna, io preferisco però la programmazione ad oggetti e quindi la implemento come membro di una classe.

Non c’è molto altro da spiegare, viene sempre utile anche se avete una cosa da mischiare, per esempio un elenco di nomi (stringhe in generale). A me è servita proprio per mischiare un elenco di file, resi in array e poi mischiati ;)