J'ai une table avec environ 100 000 livraisons de blog, liées à une table avec 50 aliments via une relation de 1: N. Lorsque j'intervèrent les deux tables avec une instruction SELECT, commandée par un champ DateTime de la table d'affichage, MySQL utilise toujours des fichiers, entraînant des temps de requête très lents (> 1 seconde). Voici le schéma de la table postings
(simplifié):
+---------------------+--------------+------+-----+---------+----------------+
| 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 | |
+---------------------+--------------+------+-----+---------+----------------+
Et voici le tableau 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 | |
+-------------+--------------+------+-----+---------+----------------+
Et voici la requête qui prend> 1 seconde pour exécuter. Veuillez noter que le post_date
Le champ a un index, mais MySQL ne l'utilise pas pour trier la table d'affichage:
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
Le résultat de la explain extended
Commande sur cette requête montre que MySQL utilise FIXTORT:
+----+-------------+----------+--------+---------------------------------------+-----------+---------+--------------------------+-------+-----------------------------+
| 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 |
+----+-------------+----------+--------+---------------------------------------+-----------+---------+--------------------------+-------+-----------------------------+
Quand je supprime le order by
Partie, MySQL arrête d'utiliser des fichiers. S'il vous plaît laissez-moi savoir si vous avez des idées sur la manière d'optimiser cette requête pour obtenir MySQL trier et sélectionner les données à l'aide de index. J'ai déjà essayé quelques choses telles que la création d'un indice combiné sur tout où/la commande par champs, comme suggéré par quelques publications de blog, mais cela n'a pas fonctionné non plus.
En outre, il est important de rappeler que MySQL n'utilisera pas d'index si la colonne que vous commandez par a une fonction appliquée à celle-ci.
Vous devriez aussi essayer des postes d'aliasing.post_date comme autre chose. Cela indiquera à MySQL de commander par la colonne Unaltered et vous sélectionnerez toujours l'horodatage UNIX.