In che modo MySQL elabora ORDER BY e LIMIT in una query?


251

Ho una query simile a questa:

SELECT article FROM table1 ORDER BY publish_date LIMIT 20

Come funziona ORDER BY? Ordinerà tutti i record, quindi otterrà i primi 20 o otterrà 20 record e li ordinerà dal publish_datecampo?

Se è l'ultimo, non sei sicuro di ottenere davvero gli ultimi 20 articoli.


6
Nota che se alcuni publish_dates sono uguali, l'ordinamento da essi non dà risultati determinati, il che significa che se usi LIMITper l'impaginazione, potresti finire per ottenere gli stessi articoli su pagine diverse!
Konrad Morawski,

Risposte:


244

Ordinerà per primo, quindi otterrà i primi 20. Un database elaborerà anche qualsiasi cosa nella WHEREclausola prima ORDER BY.


1
Quindi il tempismo è lo stesso?
Yasar Arafath,

7
Sbagliato! LIMITsi rompe ORDER BY. Con LIMITun ORDER BYrisultato sbagliato restituisce. LIMITin qualche modo riordina il set di risultati restituito daORDER BY
Green

6
@Verde, ti sbagli. Leggi questo per la spiegazione: dev.mysql.com/doc/refman/5.7/en/limit-optimization.html Quando la colonna ORDER BY è indicizzata, può restituire i record in un ordine diverso rispetto a senza LIMIT, quando ci sono più di 1 record con lo stesso valore in quella colonna.
yitwail,

1
Una soluzione rapida per tali problemi è aggiungere un'altra colonna all'ordine preferibilmente con valori univoci in modo che il database ottenga una regola coerente per ordinare le righe quando il valore del primo ordine per colonna è lo stesso per più righe.
rineez,

37

La clausola LIMIT può essere utilizzata per limitare il numero di righe restituite dall'istruzione SELECT. LIMIT accetta uno o due argomenti numerici, che devono essere entrambi costanti intere non negative (tranne quando si usano istruzioni preparate).

Con due argomenti, il primo argomento specifica l'offset della prima riga da restituire e il secondo specifica il numero massimo di righe da restituire. L'offset della riga iniziale è 0 (non 1):

SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15

Per recuperare tutte le righe da un determinato offset fino alla fine del set di risultati, è possibile utilizzare un numero elevato per il secondo parametro. Questa istruzione recupera tutte le righe dalla 96a riga all'ultima:

SELECT * FROM tbl LIMIT 95,18446744073709551615;

Con un argomento, il valore specifica il numero di righe da restituire dall'inizio del set di risultati:

SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows

In altre parole, LIMIT row_count è equivalente a LIMIT 0, row_count.

Tutti i dettagli su: http://dev.mysql.com/doc/refman/5.0/en/select.html


Non recupera le righe 5-14?
Adonis K. Kakoulidis,

@adonis No, non lo è. L'esempio è tratto dalla documentazione di MySQL
dcaswell,

Il numero 5 è la sesta fila. 5 righe (da 0 a 4) vengono ignorate.
Phil Perry,

1
Ma l'utilizzo di LIMIT senza ORDER BY può dare risultati incoerenti! Sfortunatamente, l'intero set di risultati deve essere ordinato prima dell'applicazione del LIMIT o il DBMS è libero di ordinare arbitrariamente il risultato e quindi OFFSET e LIMIT su quel set. Ho letto che ciò potrebbe essere dovuto al fatto che DBMS ha selezionato un piano di query alternativo basato su OFFSET e LIMIT, quindi l'ordine arbitrario.
Barton,

4
domanda sta ponendo il limite e ordina per. Ma la risposta non è affatto collegata a questa domanda
Shen liang,

9

Proprio come dice @James, ordinerà tutti i record, quindi otterrà le prime 20 righe.

Così com'è, avrai la garanzia di ottenere i primi 20 articoli pubblicati, i nuovi non verranno mostrati.

Nella tua situazione, ti consiglio di aggiungere desca order by publish_date, se vuoi gli articoli più recenti, allora l'articolo più recente sarà il primo.

Se devi mantenere il risultato in ordine crescente e desideri ancora solo i 10 articoli più recenti, puoi chiedere a mysql di ordinare il risultato due volte.

Questa query seguente ordinerà il risultato in ordine decrescente e limiterà il risultato a 10 (ovvero la query all'interno della parentesi). Sarà comunque ordinato in ordine decrescente e non ne siamo soddisfatti, quindi chiediamo a mysql di ordinarlo ancora una volta. Ora abbiamo il risultato più recente sull'ultima riga.

select t.article 
from 
    (select article, publish_date 
     from table1
     order by publish_date desc limit 10) t 

order by t.publish_date asc;

Se hai bisogno di tutte le colonne, è fatto in questo modo:

select t.* 
from 
    (select * 
     from table1  
     order by publish_date desc limit 10) t 

order by t.publish_date asc;

Uso questa tecnica quando scrivo manualmente query per esaminare il database per varie cose. Non l'ho usato in un ambiente di produzione, ma ora quando lo contrassegno in panchina, l'ordinamento extra non influisce sulle prestazioni.


2
Il tuo ordinamento extra non può praticamente avere alcun impatto misurabile sulle prestazioni poiché è limitato a solo 10 righe / elementi :-). In generale l'ordinamento di una tabella in memoria (che sta producendo una sottoselezione) è molto veloce e misurabile a malapena a meno che non abbiate milioni di righe o il DBMS stia eseguendo il paging del set di risultati su disco poiché non si adatta alla memoria (nel qual caso a seconda del DBMS può anche interrompere la query).
Martin Kersten,

7

Se sul campo è presente un indice adatto, in questo caso sul publish_datecampo, MySQL non ha bisogno di scansionare l'intero indice per ottenere i 20 record richiesti: i 20 record saranno trovati all'inizio dell'indice. Ma se non esiste un indice adatto, sarà necessaria una scansione completa della tabella.

Su questo c'è un articolo di MySQL Performance Blog del 2009.


7

È possibile aggiungere [asc] o [desc] alla fine dell'ordine per ottenere i record più recenti o più recenti

Ad esempio, questo ti darà prima gli ultimi record

ORDER BY stamp DESC

Aggiungi la LIMITclausola dopoORDER BY


3
Benvenuto in StackOverflow. Penso che potresti aver frainteso la domanda. Credo che stessero chiedendo l'ordine delle operazioni piuttosto che "come ordinare". (Ma è discutibile da quando alla domanda era già stata data risposta qualche tempo fa;)
Leigh,

5

È possibile utilizzare questo codice SELECT article FROM table1 ORDER BY publish_date LIMIT 0,10 dove 0 è un limite iniziale del record e 10 numero del record


8
No non è richiesto . LIMIT 10è una scorciatoia per LIMIT 0,10.
Lawrence Dol,

2
si, non richiesto per LIMIT 0,10 ma puoi richiedere come questo limite 10,20
gaurangkathiriya

3

LIMIT viene di solito applicato come ultima operazione, quindi il risultato verrà prima ordinato e quindi limitato a 20. In effetti, l'ordinamento si interromperà non appena vengono trovati i primi 20 risultati ordinati.


11
La tua seconda frase va contro la tua prima. L'ordinamento non può fermarsi quando vengono trovati i primi 20 risultati perché, come hai detto, l'ordinamento verrà eseguito prima che i risultati vengano restituiti. MySQL può sapere quali sono i primi 20 risultati solo al termine dell'ordinamento.
Tom,

@ Tom, in realtà può farlo, se si ordina da una colonna indicizzata. È spiegato qui: dev.mysql.com/doc/refman/5.7/en/limit-optimization.html
yitwail

-3

Anche la sintassi di LIMIT è diversa a seconda dei database, ad esempio:

mysql - LIMIT 1, 2

postgres - LIMIT 2 OFFSET 1

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.