Mysql
 sql >> Database >  >> RDS >> Mysql

Ottenere dati casuali da un database MySQL ma non ripetere i dati

La selezione di righe casuali è sempre complicata e non esistono soluzioni perfette che non comportino alcun compromesso. O compromettere le prestazioni, o compromettere anche la distribuzione casuale, o compromettere la possibilità di selezionare duplicati, ecc.

Come menziona @JakeGould, qualsiasi soluzione con ORDER BY RAND() non scala bene. Man mano che il numero di righe nella tabella aumenta, il costo dell'ordinamento dell'intera tabella in un filesort peggiora sempre di più. Jake ha ragione sul fatto che la query non può essere memorizzata nella cache quando l'ordinamento è casuale. Ma non mi interessa molto perché di solito disattivo comunque la cache delle query (ha i suoi problemi di scalabilità).

Ecco una soluzione per pre-randomizzare le righe nella tabella, creando una colonna rownum e assegnando valori consecutivi univoci:

ALTER TABLE products ADD COLUMN rownum INT UNSIGNED, ADD KEY (rownum);
SET @rownum := 0;
UPDATE products SET rownum = (@rownum:[email protected]+1) ORDER BY RAND();

Ora puoi ottenere una riga casuale tramite una ricerca nell'indice, senza ordinamento:

SELECT * FROM products WHERE rownum = 1;

Oppure puoi ottenere la prossima riga casuale:

SELECT * FROM products WHERE rownum = 2;

Oppure puoi ottenere 10 righe casuali alla volta, o qualsiasi altro numero desideri, senza duplicati:

SELECT * FROM products WHERE rownum BETWEEN 11 and 20;

Puoi ri-randomizzare ogni volta che vuoi:

SET @rownum := 0;
UPDATE products SET rownum = (@rownum:[email protected]+1) ORDER BY RAND();

È ancora costoso eseguire l'ordinamento casuale, ma ora non è necessario eseguirlo su ogni query SELECT. Puoi farlo in base a un programma, si spera in orari non di punta.