10
votes

MySQL Nombre lent dans la requête

J'ai donc deux tables que je dois pouvoir obtenir des comptes pour. L'un d'eux détient le contenu et l'autre sur la relation entre elle et la table des catégories. Voici le DDL:

mysql> explain SELECT count(*) FROM  content_page_categories USE INDEX (combo) I<br>
NNER JOIN content_en USE INDEX (combo) ON (id = itemid) WHERE  catid = 1 AND act<br>
ive = 1 ;

+----+-------------+-------------------------+-------+---------------+-------+---------+--------------------------+--------+--------------------------+
| id | select_type | table                   | type  | possible_keys | key   | key_len | ref                      | rows   | Extra                    |
+----+-------------+-------------------------+-------+---------------+-------+---------+--------------------------+--------+--------------------------+
|  1 | SIMPLE      | content_en              | index | combo         | combo | 6 | NULL                     | 125288 | Using where; Using index |
|  1 | SIMPLE      | content_page_categories | ref   | combo         | combo | 8 | const,mcms.content_en.id |      1 | Using where; Using index |
+----+-------------+-------------------------+-------+---------------+-------+---------+--------------------------+--------+--------------------------+
2 rows in set (0.00 sec)


12 commentaires

Essayez d'utiliser SELECT Count (1) ou SELECT compte ('x') . Les deux peuvent être plus rapides que SELECT Count (*) .


fait ça, aucun changement.Count (index) ne fait pas de diff.


Serait-il possible pour vous de poster la définition d'index s'il vous plaît?


Mieux appendez ces tentatives pour votre question. Ils sont très difficiles à lire comme un commentaire.


J'ai ajouté les définitions d'index


Pouvez-vous inclure la sortie de 'Desc' de votre requête?


Si vous vous référez à la description des champs et description, ils sont vides


Je pensais à la déclaration «Desc» comme synonyme de 'Expliquer': dev.mysql.com/doc/refman/5.0/fr/Unding-Explain.html


Explique ajoutée aussi


Vos scripts de données ne correspondent pas aux définitions de la table


@Quassnoi, juste tomber des colonnes content_en.description et content_en.description_long .


C'est la bonne façon de demander quelque chose. Nice et détaillé. +1


5 Réponses :


1
votes

Le problème est la colonne "Active" dans Content_en. Évidemment, si vous avez juste besoin de savoir combien de registres de contenu étaient liés à une catégorie particulière (active ou non), tout ce que vous aurez à faire est de:

SELECT count(1)
FROM content_page_categories USE INDEX (combo)
WHERE catid = 1 AND active = 1;


0 commentaires

5
votes

Il y a trop de dossiers à compter.

Si vous voulez une solution plus rapide, vous devrez stocker des données agrégées. P>

mysql ne prend pas en charge les vues matérialisées (ou vues indexées dans SQL Server Termes) Vous auriez donc besoin de les créer et de les maintenir vous-même. P>

Créer une table: p> xxx pré>

puis remplissez-le: p>

SELECT  cnt
FROM    page_active_category
WHERE   active = 1
        AND catid = 1


2 commentaires

Je pense que la voie à suivre est désordonnée (code sage), c'est-à-dire les tables de synthèse. J'ai toujours détesté les tables de synthèse car elles ont tendance à augmenter le nombre de bogues dans l'application. La chose est, comme si j'étais énoncé dans ma question, j'ai essayé toutes les autres solutions - la proposition indiquée ici et a échoué. 200ms pour un décompte unique est inacceptable, les tables récapitulatives semblent être une route aller simple. Merci.


@MBOUCLAS: Dans SQL Server et Oracle, vous pouvez les avoir auto-remplis et automatiquement mis à jour, comme des index. MySQL a besoin d'une telle caractéristique aussi.



0
votes

Pour moi avec vos données en tant que configuration, je recevais la requête de jointure de la prise de la requête ~ 50x fois plus longtemps que de simplement sélectionner à partir du contenu_page_categories.

J'ai pu obtenir des performances d'environ 10 fois plus lentement que de simplement choisir de la table des catégories en faisant Les éléments suivants avec vos données:

J'ai utilisé droit_join xxx

et la structure de table suivante (légèrement modifiée): xxx < / pré>

and: xxx

Pour obtenir mieux que cela, je pense que vous aurez besoin d'une vue, une structure aplatie ou un autre type de champ de recherche (comme dans la gâchette pour peupler une rangée dans l'autre table comme indiquée par une autre affiche).

EDIT:

Je devrais également indiquer ce message décent sur pourquoi / quand faire attention avec < Code> droite_join : Quand utiliser straight_join avec mysql

si Vous l'utilisez, utilisez-le de manière responsable!


0 commentaires

12
votes

J'ai téléchargé vos données et j'ai essayé quelques expériences. Je couronne MySQL 5.6.12 sur une machine virtuelle Centos sur un MacBook Pro. Les temps que j'ai observés peuvent être utilisés à titre de comparaison, mais votre système peut avoir des performances différentes.

Base de base H2>

J'ai d'abord essayé sans les clauses d'index d'utilisation, car j'évite les remplissages d'optimisation dans la mesure du possible. Dans la plupart des cas, une simple requête comme celle-ci devrait utiliser l'index correct s'il est disponible. Codage rigide Le choix d'index dans une requête rend plus difficile l'utilisation d'un meilleur index plus tard. P>

J'utilise également des noms de corrélation (alias de table) pour rendre la requête plus claire. P>

mysql> CREATE TABLE page_active_category (
 active INT NOT NULL, 
 catid INT NOT NULL, 
 cnt BIGINT NOT NULL,
 PRIMARY KEY (active, catid) 
) ENGINE=InnoDB;

mysql> INSERT INTO page_active_category
 SELECT  e.active, c.catid, COUNT(*)
 FROM    content_en AS e
 JOIN    content_page_categories AS c ON c.itemid = e.id
 GROUP BY e.active, c.catid

mysql> SELECT cnt FROM page_active_category WHERE active = 1 AND catid = 1
  • ceci exécuté en 0.36 secondes. li> ul>

    Index de couverture h2>

    J'aimerais obtenir "en utilisant l'index" sur la deuxième table, donc j'ai besoin d'un index sur (actif, ID) dans cet ordre. J'ai dû utiliser l'index dans ce cas pour persuader l'optimiseur de ne pas utiliser la clé primaire. P>

    mysql> ALTER TABLE content_page_categories ADD COLUMN active TINYINT(1);
    mysql> UPDATE content_en JOIN content_page_categories ON id = itemid 
        SET content_page_categories.active = content_en.active;
    mysql> ALTER TABLE content_page_categories ADD KEY combo3 (catid,active);
    mysql> SELECT COUNT(*) FROM content_page_categories WHERE catid = 1 and active = 1;
    


0 commentaires

0
votes

Pour accélérer le comptage sur MySQL rejoint les sous-requêtes.

Par exemple, obtenir des villes avec placomount

Table de ville

ID Titre ......

Table Place

ID city_id Titre ..... xxx


0 commentaires