Ho una tabella di grandi dimensioni con circa 100 milioni di record, con campi start_date
e end_date
, con tipo DATE
. Devo controllare il numero di sovrapposizioni con un intervallo di date, ad esempio tra 2013-08-20
E 2013-08-30
, Quindi io uso.ricerca per data prestazione mysql
SELECT COUNT(*) FROM myTable WHERE end_date >= '2013-08-20'
AND start_date <= '2013-08-30'
colonna di data sono indicizzati. I punti importanti sono che gli intervalli di date che sto cercando di sovrapporre sono sempre in futuro, mentre la parte principale dei record nella tabella sono nel passato (ad esempio circa 97-99 milioni). Quindi, sarà questa query più veloce, se posso aggiungere una colonna is_future - TINYINT
, quindi, controllando solo che condizione come questa
SELECT COUNT(*) FROM myTable WHERE is_future = 1
AND end_date >= '2013-08-20' AND start_date <= '2013-08-30'
che esclude il resto 97 milioni o giù di lì dischi e controllerà la condizione data solo i restanti 1-3 milioni di dischi?
Io uso MySQL
Grazie
EDIT
Il motore di MySQL è InnoDB, ma importa molto se si tratta di dire, MyISAM
qui è la tabella di creare
CREATE TABLE `orders` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`title`
`start_date` date DEFAULT NULL,
`end_date` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
EDIT 2 dopo @ Robert Co rispondere
Il partizionamento si presenta come una buona idea per questo caso, ma non mi permette di creare partizioni in base a is_future
campo a meno che io definisco come chiave primaria, altrimenti dovrei rimuovere la mia chiave primaria principale - id, che non posso fare. Quindi, se definisco quel campo come chiave primaria, allora c'è un significato di partizionamento, non sarà veloce già se cerco nel campo is_future
che è la chiave primaria.
EDIT 3 La query effettivo in cui ho bisogno di utilizzare questo è quello di selezionare ristorante che hanno alcuni tavoli liberi per questo intervallo di date
SELECT r.id, r.name, r.table_count
FROM restaurants r
LEFT JOIN orders o
ON r.id = o.restaurant_id
WHERE o.id IS NULL
OR (r.table_count > (SELECT COUNT(*)
FROM orders o2
WHERE o2.restaurant_id = r.id AND
end_date >= '2013-08-20' AND start_date <= '2013-08-30'
AND o2.status = 1
)
)
SOLUZIONE Dopo molta più ricerca e sperimentazione del il modo più rapido per contare il numero di righe nel mio caso era quello di aggiungere solo un'altra condizione, che data_inizio è più della data corrente (perché gli intervalli di date per la ricerca sono sempre in futuro)
SELECT COUNT(*) FROM myTable WHERE end_date >= '2013-09-01'
AND start_date >= '2013-08-20' AND start_date <= '2013-09-30'
inoltre è necessario avere un indice - con i campi start_date e end_date (grazie @symcbean). Come risultato, il tempo di esecuzione su una tabella con righe da 10 m da 7 secondi è diventato 0,050 secondi.
SOLUZIONE 2 (@Robert Co) partizionamento in questo caso ha funzionato pure !! - forse è una soluzione migliore dell'indicizzazione. Oppure possono essere entrambi applicati insieme.
Grazie
Ottima domanda ... provalo e facci sapere. ;) Perché non stai usando 'BETWEEN'? – DevlshOne
@DevlshOne,: D, come utilizzare in questo caso? Confronto 2 colonne, posso? – dav
Puoi pubblicare la dichiarazione della tabella di creazione e le informazioni sul motore di archiviazione, questo è importante .. –