2015-04-07 11 views
8

Ho un'app web in cui mostro una serie di post basati su questo schema di tabella (ci sono migliaia di righe come questa e altre colonne (rimosse come non richieste per questa domanda)) : -Come dovrei interrogare questo in mysql

+---------+----------+----------+ 
| ID | COL1 | COL2 | 
+---------+----------+----------+ 
| 1  | NULL | ---- | 
| 2  | --- | NULL | 
| 3  | NULL | ---- | 
| 4  | --- | NULL | 
| 5  | NULL | NULL | 
| 6  | --- | NULL | 
| 7  | NULL | ---- | 
| 8  | --- | NULL | 
+---------+----------+----------+ 

E io uso questa domanda: -

SELECT * from `TABLE` WHERE `COL1` IS NOT NULL AND `COL2` IS NULL ORDER BY `COL1`; 

E il set di risultati risultante ottengo è come: -

+---------+----------+----------+ 
| ID | COL1 | COL2 | 
+---------+----------+----------+ 
| 12 | --- | NULL | 
| 1  | --- | NULL | 
| 6  | --- | NULL | 
| 8  | --- | NULL | 
| 11  | --- | NULL | 
| 13  | --- | NULL | 
| 5  | --- | NULL | 
| 9  | --- | NULL | 
| 17 | --- | NULL | 
| 21 | --- | NULL | 
| 23 | --- | NULL | 
| 4  | --- | NULL | 
| 32 | --- | NULL | 
| 58 | --- | NULL | 
| 61 | --- | NULL | 
| 43 | --- | NULL | 
+---------+----------+----------+ 

Si noti che la colonna ID è mescolata grazie alla clausola order by.

Ho indici adeguati per ottimizzare queste query. Ora lasciami spiegare il vero problema. Ho un tipo di funzionalità pigro nella mia app web. Pertanto, visualizzo circa 10 post per pagina utilizzando uno LIMIT 10 dopo la query per la prima pagina.

Siamo buoni fino a qui. Ma il vero problema arriva quando devo caricare la seconda pagina. Cosa chiedo ora? Non voglio che i post vengano ripetuti. E ci sono nuovi messaggi che arrivano quasi ogni 15 secondi che li fanno andare in cima (per prima cosa intendo letteralmente la prima riga) del set di risultati (non voglio visualizzare questi ultimi post nella seconda o terza pagina ma alterano il dimensione del set di risultati quindi non posso usare LIMIT 10,10 per la seconda pagina e così via in quanto i post verranno ripetuti.).

Ora, tutto quello che so è l'ultimo ID del post che ho visualizzato. Dì 21 qui. Quindi, voglio visualizzare i post degli ID 23,4,32,58,61,43 (fare riferimento alla tabella dei risultati sopra riportata). Ora, carico tutte le righe senza utilizzare la clausola LIMIT e visualizzo 10 ID che si verificano dopo l'ID 21. Ma per quello dovrò interagire su migliaia di file inutili. Ma non posso usare una clausola LIMIT per la 2a, 3a ... pagine di sicuro. Inoltre, gli ID sono confusi, quindi non posso assolutamente usare WHERE ID>.... Allora, dove andiamo ora?

+0

Dal momento che il 'COL1' è ordinabile, come a ricordare l'ultimo record di' COL1' a ogni richiesta, e in pagina seguente carico 'COL1 DOVE>?'? – Passerby

+0

@Passerby, ci ho già pensato. Ma, 'COL1' ha molte righe identiche. In realtà, 'COL1' è un timestamp e molte righe possono avere lo stesso timestamp (nel mio set di risultati) – user4647309

risposta

2

Hmm .. Ho pensato per un po 'e ho trovato 2 soluzioni. : -

  1. Per memorizzare l'Ids del post già visualizzato e interrogazione WHERE ID NOT IN(id1,id2,...). Ma questo ti costerebbe una memoria extra. E se l'utente carica 100 pagine e gli ID sono in 100000, una singola richiesta GET non sarebbe in grado di gestirla. Almeno non in tutti i browser. È possibile utilizzare una richiesta POST.

  2. Modificare il modo in cui vengono visualizzati i post da COL1. Non so se questo sarebbe un buon modo per te. Ma può salvarti la larghezza di banda e rendere il tuo codice più pulito. Potrebbe anche essere un modo migliore. Vorrei suggerire questo: - SELECT * from TABLE where COL1 IS NOT NULL AND COL2 IS NULL AND Id>.. ORDER BY ID DESC LIMIT 10,10. Questo può influenzare il modo in cui visualizzi i tuoi messaggi a passi da gigante. Ma, come hai detto nei tuoi commenti che controlli se un post soddisfa un criterio e cambi il COL1 da NULL al timestammp corrente, immagino che più il post sia nuovo, più sopra vuoi mostrarli. È solo un'idea

+0

Ho già provato il primo metodo prima. Ma non lo trovò molto fattibile. Ma penso di poter provare il tuo secondo metodo. Grazie +1 – user4647309

3

io non sono sicuro se ho capito bene la tua domanda, ma ecco come penso lo farei:

  • Aggiungere una colonna timestamp al vostro tavolo, chiamiamolo date_added
  • Quando visualizzando la prima pagina, utilizzare la query così com'è (con LIMIT 10) e aggrapparsi al timestamp del record più recente; chiamiamolo last_date_added.
  • Per i pagine 2, 3 e successive, modificare la query per filtrare tutti i record con date_added > last_date_added, e utilizzare LIMIT 10, 10, LIMIT 20, 10, LIMIT 30, 10 e così via.

Questo avrà l'effetto di congelare i risultati in tempo e di reimpostarli ogni volta che si accede alla prima pagina.

Note:

  • seconda l'ordinamento del gruppo di risultati, potrebbe essere necessario una query separata per ottenere il last_date_added. In alternativa, è possibile interrompere l'ora corrente, ovvero l'ora in cui è stata aperta la prima pagina.
  • Se i tuoi ID sono sequenziali, potresti usare lo stesso trucco con l'ID.
+0

È divertente che la colonna' COL1' sia un timestamp. Ma, sfortunatamente, come ho menzionato nel commento sopra, non è univoco dato che molte righe condividono lo stesso timestamp. Controllo se un post soddisfa un criterio e cambio 'COL1' da NULL al timestammp corrente. Quindi, se molti post soddisfano i criteri, hanno lo stesso timestamp. – user4647309

+0

@ user4647309 Quindi, perché non aggiungere un ulteriore indicatore di data 'date_added' che viene impostato quando viene inserito il record? Se si utilizza la precisione in microsecondi, dovrebbe essere abbastanza unico. Oppure, come ho detto, se i tuoi ID sono sequenziali, prima di eseguire la query per la prima pagina, potresti ottenere l'ID più alto e utilizzarlo per bloccare il set di risultati per le pagine successive. –

+2

@RobbyCornelissen Penso che il problema è che l'ordinamento di 'COL1'" rovinerebbe "l'ordinamento di' ID' o qualsiasi cosa simile: con lo stesso 'COL1' questo può essere d'aiuto, ma un' WHERE \ 'ID \ '> ? 'filtrerebbe anche alcuni risultati che hanno un' COL1' più alto ma un 'ID' più basso. – Passerby

1

Suppongo che i nuovi post verranno aggiunti con un ID superiore rispetto all'ID massimo corrente, giusto? Quindi non potresti semplicemente eseguire la tua query e prendere l'ID massimo attuale. Quindi quando si esegue una query per la pagina 2, eseguire la stessa query ma con "ID < max_id". Questo dovrebbe darti lo stesso set di risultati della tua query di pagina 1 perché ogni nuova riga avrà ID> max_id. Spero possa aiutare?

1

Che ne dici?

ORDER BY `COL1`,`ID`; 

Questo rimetterebbe sempre gli ID in ordine. Questo ti consente di utilizzare:

LIMIT 10,10 

per la tua seconda pagina.

Problemi correlati