Ho una tabella con circa 100.000 post di blog, collegata a una tabella con 50 feed tramite una relazione 1: n. Quando eseguo una query su entrambe le tabelle con un'istruzione select, ordinata da un campo datetime della tabella dei post, MySQL utilizza sempre filesort, risultando in tempi di query molto lenti (> 1 secondo). Ecco lo schema della tabella postings
(semplificato):Ottimizzazione delle prestazioni MySQL: ordine per data/ora
+---------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| feed_id | int(11) | NO | MUL | NULL | |
| crawl_date | datetime | NO | | NULL | |
| is_active | tinyint(1) | NO | MUL | 0 | |
| link | varchar(255) | NO | MUL | NULL | |
| author | varchar(255) | NO | | NULL | |
| title | varchar(255) | NO | | NULL | |
| excerpt | text | NO | | NULL | |
| long_excerpt | text | NO | | NULL | |
| user_offtopic_count | int(11) | NO | MUL | 0 | |
+---------------------+--------------+------+-----+---------+----------------+
Ed ecco il tavolo feed
:
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| type | int(11) | NO | MUL | 0 | |
| title | varchar(255) | NO | | NULL | |
| website | varchar(255) | NO | | NULL | |
| url | varchar(255) | NO | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
Ed ecco la domanda che prende> 1 secondo per eseguire. Si prega di notare che il campo post_date
ha un indice, ma MySQL non è utilizzarlo per ordinare la tabella messaggi:
SELECT
`postings`.`id`,
UNIX_TIMESTAMP(postings.post_date) as post_date,
`postings`.`link`,
`postings`.`title`,
`postings`.`author`,
`postings`.`excerpt`,
`postings`.`long_excerpt`,
`feeds`.`title` AS feed_title,
`feeds`.`website` AS feed_website
FROM
(`postings`)
JOIN
`feeds`
ON
`feeds`.`id` = `postings`.`feed_id`
WHERE
`feeds`.`type` = 1 AND
`postings`.`user_offtopic_count` < 10 AND
`postings`.`is_active` = 1
ORDER BY
`postings`.`post_date` desc
LIMIT
15
Il risultato del comando explain extended
su questa query mostra che MySQL sta usando filesort:
+----+-------------+----------+--------+---------------------------------------+-----------+---------+--------------------------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+--------+---------------------------------------+-----------+---------+--------------------------+-------+-----------------------------+
| 1 | SIMPLE | postings | ref | feed_id,is_active,user_offtopic_count | is_active | 1 | const | 30996 | Using where; Using filesort |
| 1 | SIMPLE | feeds | eq_ref | PRIMARY,type | PRIMARY | 4 | feedian.postings.feed_id | 1 | Using where |
+----+-------------+----------+--------+---------------------------------------+-----------+---------+--------------------------+-------+-----------------------------+
Quando rimuovo la parte order by
, MySQL smette di utilizzare filesort. Per favore fatemi sapere se avete qualche idea su come ottimizzare questa query per ottenere MySQL per ordinare e selezionare i dati utilizzando gli indici. Ho già provato alcune cose, come la creazione di un indice combinato su tutti i campi in cui ordinare/per campo, come suggerito da alcuni post di blog, ma anche questo non ha funzionato.
Mi piace molto il modo chiaro e dettagliato che hai chiesto. – tpdi