Domanda

CREATE TEMPORARY TABLE tt;
INSERT INTO tt; many times
SELECT FROM tt ORDER BY id LIMIT ?,1000;

La tabella temporanea viene creata all'inizio dello script avere una colonna "id" auto_increment (e altri). Parte 1 dello script riempie la tabella con i vari SELECT. Parte 2 deve elaborare tutte le righe selezionate in pezzi di 1000, ma non sarà mai mai scrivere di nuovo al tavolo.

I assumere che questi due comandi sono gli stessi

SELECT FROM tt ORDER BY id LIMIT ?,1000;
SELECT FROM tt LIMIT ?,1000;

, ma è vero? C'è qualche possibilità che MySQL retrive le righe in un ordine diverso su più SELECT anche se la tabella non è scritto in mezzo?

Ordinamento della tabella temporanea è la parte più lunga durante la lettura e sarei felice di sbarazzarsi di ORDER BY parte, ma non voglio perdere un record perché l'ordine è cambiato tra SELEZIONA LIMIT 0,1000 e selezionare LIMIT 1000,1000.

È stato utile?

Soluzione

Credo che questo dipende dalla conservazione a motore. Posso dire per MyISAM, un selezionare senza alcun ordine tornerà file in sequenza che si verificano nel file (anche se tenuto in memoria).

Come si è ordinata dei dati durante la scrittura, che sarà ordinato in base id entro MyISAM-temptables. Così si può tranquillamente supporre che tornerà sempre risultati corretti finché non si eliminano da MyISAM-temp.

Ma la nuova domanda è - si TempTable creato in MyISAM formato? Presumo verrà utilizzato il motore di memorizzazione predefinito. Questo usato per essere MyISAM, ma è stato cambiato a InnoDB dopo MySQL 5.1.

Non so come InnoDB sarebbe gestire un non ordinato di selezione.

- modifica

http://dev.mysql.com/ doc / refman / 5.1 / it / interno-temporanea-tables.html

Nel grande (su disco) le tabelle temporanee MyISAM viene utilizzato. Si tratta di non filari comportamento intenzionale sono serviti in sequenza in ordine come scritto in, ma è legato alla progettazione (come documentato) è affidabile finché tabella MyISAM viene aggiunto solo.

Questa è molto probabilmente non è vero per qualsiasi "tabella hash", come InnoDB, BDB, e alla fine MEMORIA. Ma quando tabella di memoria viene convertito in "sul tavolo del disco", l'ordine attuale è "congelata sul disco", e quindi affidabile di nuovo.

Ma credo che abbiamo un altro tipo di problema qui:

  • Il problema e 'reale' sembra essere il vostro "ordine da" sente troppo lento, e si vorrebbe ottenere intorno a quello. si fa per caso conoscere la dimensione del tavolo e sedute max_heap_table_size? Questo vi darà un suggerimento se la tabella è stato convertito in MyISAM. Si può anche giocare con Index-Hash-metodo (BTREE, cancelletto) per cercare l'ottimizzazione.

  • Sei consapevole che LIMITE N, M otterrà dolorosamente lento perché deve selezionare N righe, disfarsene, e quindi selezionare M righe da restituire?

Altri suggerimenti

Questo non è direttamente correlata alla ORDER BY, ma attenzione utilizzando il modello LIMIT N, M. Questo è spesso usato per i risultati impaginazione, per es.

... limit 0,10;
... limit 10,10;
... limit 20,10;

Ogni volta che attraverso mysql "selezionare" i primi N righe e proprio ritorno l'ultimo M al cliente. Come si va sempre più in profondità si sta selezionando sempre di più di righe, solo per essere buttato via.

In breve ogni "pagina" richiede più tempo per il carico. Se i set di dati sono di piccole dimensioni e le query stanno usando gli indici bene questo può sembrare insignificante, ma l'effetto sarà evidente come si cresce. Sento che è generalmente meglio mettere questi vincoli nella clausola dove. per es.

... where id between 0 and 10;
... where id between 11 and 20;
... where id between 21 and 30;

Infine, se siete preoccupati per l'ordinamento per la limitazione crea effettivamente le restrizioni intervallo corretto per voi allora questa preoccupazione è completamente eliminati per cominciare.

Al posto della vostra query originale

SELECT FROM tt ORDER BY id LIMIT ?,1000;

si consiglia di refactoring la query tp applicare l'ordine contro solo i tasti e unire le chiavi alla tabella originale:

SELECT tt.*
FROM
(
    SELECT id FROM tt
    ORDER BY id LIMIT ?,1000
) ttkeys
LEFT JOIN tt USING (id);

Questo può essere fatto per imporre a 1000 chiavi di unirsi contro la tabella originale.

utilizzo LEFT JOIN anziché INNER JOIN perché LEFT JOIN mantiene l'ordine delle chiavi dopo il join è completo, mentre INNER JOIN tende ad annullare l'ordinamento nella sottoquery.

Se facendo questo contro una tabella temporanea interna ha problemi, quindi provare con un tabella temporanea esterna come segue:

CREATE TEMPORARY TABLE tt;
INSERT INTO tt; many times
CREATE TEMPORARY TABLE ttkeys
    SELECT id FROM tt
    ORDER BY id LIMIT 1000
;
ALTER TABLE ttkeys ADD PRIMARY KEY (id);
SELECT tt.* FROM ttkeys
LEFT JOIN tt USING (id);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a dba.stackexchange
scroll top