2009-09-01 3 views
6

Come alcuni di voi potrebbero sapere, l'uso della parola chiave LIMIT in MySQL non preclude la lettura dei record precedenti.Come impaginare in modo efficiente dataset di grandi dimensioni con PHP e MySQL?

Ad esempio:

SELECT * FROM my_table LIMIT 10000, 20; 

Significa che MySQL sarà ancora leggere i primi 10.000 record e buttarli via prima di produrre il 20 ci sono dopo.

Quindi, quando si impagina un set di dati di grandi dimensioni, i numeri di pagina elevati significano tempi di caricamento lunghi.

Qualcuno conosce una classe/tecnica/metodologia di impaginazione esistente che può impaginare dataset di grandi dimensioni in un modo più efficiente, cioè che non si basa sulla parola chiave LIMIT MySQL?

In PHP, se possibile, è l'arma scelta dalla mia azienda.

Cheers.

+2

Se il set di dati non è suscettibile di modifiche, è possibile calcolare l'indice di pagina per ciascun elemento sullo sfondo, quindi il paging diventa una selezione in un campo indicizzato. quello che potrebbe accadere è che accidentalmente avrete n + 1 elementi in una pagina ogni tanto. – Zed

+2

http://stackoverflow.com/questions/1243952/how-can-i-speed-up-a-mysql-query-with-a-large-offset-in-the-limit-clause – Sampson

risposta

1

Una soluzione potrebbe essere quella di non utilizzare la clausola limite e utilizzare invece un join - unirsi a una tabella utilizzata come una sorta di sequenza.

Per maggiori informazioni, su SO, ho trovato questo question/answer, che dà un esempio - che potrebbero aiutare a ;-)

+1

Grazie amico darò un'occhiata! – Evernoob

0

Non sono a conoscenza del calo delle prestazioni che hai menzionato e non conosco altre soluzioni per l'impaginazione, tuttavia una clausola ORDER BY potrebbe aiutarti a ridurre il tempo di caricamento.

0

Il modo migliore è definire il campo dell'indice in my_table e per ogni nuova riga inserita è necessario incrementare questo campo. E dopo tutto è necessario utilizzare DOVE YOUR_INDEX_FIELD TRA 10000 E 10020 Sarà molto più veloce.

+1

Ciò richiede che tu non sia mai elimina tutte le righe e non visualizzi aggregati. – nos

1

Ci sono fondamentalmente 3 approcci a questo, ognuno dei quali hanno le loro trade-off :

  1. inviare tutti i 10000 record per il cliente, e di gestire la paginazione lato client tramite JavaScript o simili. Il vantaggio ovvio è che solo una singola query è necessaria per tutti i record; ovvio svantaggio è che se la dimensione del record è in qualche modo significativa, la dimensione della pagina inviata al browser sarà di dimensioni proporzionate e l'utente potrebbe non preoccuparsi del set di record completo.

  2. Fai ciò che stai facendo attualmente, ovvero SQL LIMIT e prendi solo i record necessari per ogni richiesta, completamente privi di stato. Beneficio del fatto che invia solo i record per la pagina attualmente richiesta, quindi le richieste sono piccole, aspetti negativi in ​​quanto a) richiede una richiesta server per ogni pagina e eb) è più lento come il numero di record/pagine aumenta per le pagine successive in il risultato, come hai detto tu. L'utilizzo di una clausola JOIN o WHERE su un campo di identificazione monotono crescente può a volte aiutare a questo proposito, in particolare se si richiedono risultati da una tabella statica rispetto a una query dinamica.

  3. Mantenere una sorta di oggetto stato sul server che memorizza nella cache i risultati della query e può essere fatto riferimento in richieste future per un periodo di tempo limitato. Il lato positivo è che ha la migliore velocità di interrogazione, poiché la query effettiva deve essere eseguita solo una volta; il rovescio della medaglia è dover gestire/archiviare/ripulire quegli oggetti di stato (particolarmente sgradevoli per i siti Web ad alto traffico).

0

alcune altre opzioni,

  • di ripartizione delle tabelle per ogni pagina in modo ignorano il limite
  • memorizzare i risultati in una sessione (una buona idea sarebbe quella di creare un hash di tali dati utilizzando md5, quindi usare quella cache per più utenti)
+0

non è proprio un fan di memorizzazione di un set di dati così grande in una sessione – Evernoob

6

Prima di tutto, se si desidera eseguire la paginazione, è assolutamente necessario avere una clausola ORDER BY. Quindi devi semplicemente usare quella clausola per scavare più a fondo nel tuo set di dati. Ad esempio, si consideri questo:

SELECT * FROM my_table ORDER BY id LIMIT 20 

avrai i primi 20 record, diciamo loro ID sono: 5,8,9, ..., 55,64. Il link di impaginazione alla pagina 2 sarà simile "list.php? Page = 2 & id = 64" e la query sarà

SELECT * FROM my_table WHERE id > 64 ORDER BY id LIMIT 20 

No compensato, a soli 20 record letti. Non ti permette di saltare arbitrariamente a nessuna pagina, ma la maggior parte delle volte le persone sfogliano solo la pagina successiva/precedente. Un indice su "id" migliorerà le prestazioni, anche con valori OFFSET grandi.

+0

L'unica cosa che non tiene conto delle righe eliminate (presuppone numerazione coerente per gli id) ... –

+0

È una buona idea, ma sì, anch'io ho bisogno dei numeri di pagina, il che significa che dovrei a) non cancellare mai alcuna riga o b) calcolare e memorizzare da qualche parte gli ID di ogni record che termina ogni pagina. – Evernoob

+0

se non si ottengono abbastanza righe, è sufficiente richiederne altre. continuare a richiedere in gruppi fino a quando non si ottiene abbastanza, oppure si ottiene 0 (il che significa che non ci sono più righe). assicurati di tenere traccia di dove si trova la fine effettiva, in modo che il successivo gruppo di righe sia contiguo con ciò che è stato mostrato all'utente, non ciò che è stato recuperato. – longneck

1
SELECT * FROM my_table LIMIT 10000, 20; 

mezzi mostrano 20 record a partire dal record # 10000 nella ricerca, se ur utilizzando chiavi primarie nella clausola in cui non ci sarà un carico pesante sul mio SQL

altri metodi per pagnation avrà vero e proprio carico enorme come l'utilizzo di un metodo di join