-1
votes

Améliorer les performances de la requête SQL

J'ai une requête complexe qui prend 700 ms pour fonctionner sur ma machine. J'ai constaté que le goulot d'étranglement est l'ordre par at_firstname.value strong> clause, mais comment puis-je utiliser des index pour améliorer cela? XXX PRE>

Ceci est plan d'exécution: Entrez la description de l'image ici p>

Explique de requête: P>

CREATE TABLE `customer_entity_varchar` (
  `value_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Value Id',
  `entity_type_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Entity Type Id',
  `attribute_id` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT 'Attribute Id',
  `entity_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Entity Id',
  `value` varchar(255) DEFAULT NULL COMMENT 'Value',
  PRIMARY KEY (`value_id`),
  UNIQUE KEY `UNQ_CUSTOMER_ENTITY_VARCHAR_ENTITY_ID_ATTRIBUTE_ID` (`entity_id`,`attribute_id`),
  KEY `IDX_CUSTOMER_ENTITY_VARCHAR_ENTITY_TYPE_ID` (`entity_type_id`),
  KEY `IDX_CUSTOMER_ENTITY_VARCHAR_ATTRIBUTE_ID` (`attribute_id`),
  KEY `IDX_CUSTOMER_ENTITY_VARCHAR_ENTITY_ID` (`entity_id`),
  KEY `IDX_CUSTOMER_ENTITY_VARCHAR_ENTITY_ID_ATTRIBUTE_ID_VALUE` (`entity_id`,`attribute_id`,`value`),
  CONSTRAINT `FK_CSTR_ENTT_VCHR_ATTR_ID_EAV_ATTR_ATTR_ID` FOREIGN KEY (`attribute_id`) REFERENCES `eav_attribute` (`attribute_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_CSTR_ENTT_VCHR_ENTT_TYPE_ID_EAV_ENTT_TYPE_ENTT_TYPE_ID` FOREIGN KEY (`entity_type_id`) REFERENCES `eav_entity_type` (`entity_type_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_CUSTOMER_ENTITY_VARCHAR_ENTITY_ID_CUSTOMER_ENTITY_ENTITY_ID` FOREIGN KEY (`entity_id`) REFERENCES `customer_entity` (`entity_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=131094 DEFAULT CHARSET=utf8 COMMENT='Customer Entity Varchar';


7 commentaires

Optimisation d'une requête avec les jointures avec Commander par peut être difficile. Si l'optimiseur MySQL accédait aux tables de la commande "Mauvais" Commander une tri algoritme est toujours requise .. Idéalement, l'optimiseur doit accéder à Customer_entity_varchachar en premier. . Pouvez-vous fournir des structures de table et une sortie explique?


Veuillez poster le plan d'exécution.


Il n'y a pas de filtrage dans cette requête: cela signifie que c'est essentiellement le traitement toutes les lignes du Customer_entity . Combien de rangées a-t-elle?


Vous n'avez pas assez de renseignements pour vous aider. Veuillez lire ceci, en particulier la section sur la performance de la requête, puis Modifier Votre question. meta.stackoverflow.com/a/271056


@Impaler c'est la liste des utilisateurs, peut-être des milliers


Pouvez-vous publier un indigène mysql expliquer sortie? De plus, nous manquons toujours des structures de table.


@Raymondnijland Expliquez-vous ajouté à la question.


3 Réponses :


3
votes

Dès maintenant votre requête est la suivante:

  1. Effectuer tout le reste de la sortie extérieure gauche.
  2. alors commande les lignes.
  3. alors limite ing les lignes.

    J'effectueriez d'abord les jointures extérieures strictement nécessaires, puis commandez et limitant (réduire à 20 rangées), puis je ferais enfin tout le reste des jointures extérieures. En bref, je ferais:

    1. Effectuer d'abord une jointure externe gauche minimale gauche. C'est-à-dire deux tables seulement.
    2. alors commande les lignes.
    3. alors limite les rangées. Cela produisent un maximum de 20 rangées.
    4. Effectuez tout le reste des jointures extérieures. À ce stade, ce n'est plus des milliers de rangées, mais seulement 20.

      Ce changement devrait réduire massivement les exécutions "de la recherche clé unique". La requête modifiée ressemblera à: xxx


4 commentaires

Parce que les résultats SQL sont sans commande par définition, le SQL externe nécessite également une commande par e.firstname pour garantir des résultats cohérents?


Si la commande est vraiment requise, oui. À ce stade, il est déjà filtré à 20 rangées, il peut donc être inutile.


Typo mineur, en ligne 10 Remplacer **, Concat (AT_FirstName.Value ** avec **, Concat (prénom **


@Avebrahimi Typo Fixe.



3
votes

Malheureusement, Sélectionnez tout_mess_of_rows à partir de plusieurs_tables Commandez par One_Col Limit Small_Number est une performance notoire antiparatère. Pourquoi? Parce qu'il trie un grand ensemble de résultats, juste pour se défaire la plupart d'entre eux.

L'astuce consiste à rechercher à moindre coût quelles lignes sont à l'intérieur de ce Limiter le petit nombre , puis récupérez uniquement ces lignes de la plus grande requête.

Quelles rangées voulez-vous? Il me semble que cette requête récupérera leur customer_entity.id valeurs. Mais il est difficile d'être sûr, vous devriez donc tester cette sous-requête. xxx

ceci devrait donner aux vingt valeurs d'entité pertinentes. Essaye-le. Regardez son plan d'exécution. Ajoutez un index approprié à Customer_entity Si besoin d'être. Cet index pourrait être (fiateName_aTtribute_id, prénomname_entity_id, prénomname_value) mais je devine.

alors vous pouvez mettre cela à la fin de votre requête principale, juste avant l'ordre par. xxx

et les choses doivent être un peu plus rapides.


0 commentaires

1
votes

Je suis d'accord avec les réponses précédentes, mais je veux mettre l'accent sur plus d'antidiatern: sur-noramlization.

Votre schéma est une variante curieuse (et inefficace) sur le modèle de schéma déjà mauvais.

Il y a peu d'avantages et un inconvénient dans la scission Customer_Address_entity_varchars sur 5 tables. De même pour Customer_entity_varchar .

Une adresse doit être stockée comme quelques colonnes dans une seule table; No joint à d'autres tables.

De même pour FirstName + Nom.

téléphone pourrait être un autre problème, puisque une personne / une entreprise / entité pourrait avoir plusieurs numéros de téléphone (cellule, maison, travail, fax, etc.). Mais c'est une histoire différente.


0 commentaires