2009-12-15 8 views
0

J'ai la requête ci-dessous ... Cela fonctionne mais il fonctionne extrêmement lent. Est-ce que j'espérais que quelqu'un pourrait me donner quelques conseils pour améliorer le temps d'exécution?Requête mysql lente. Des conseils?

SELECT tb_clients.*, tb_clients_phone_fax.* 
FROM tb_clients, tb_clients_phone_fax 
WHERE tb_clients.client_id=tb_clients_phone_fax.client_id 
AND MATCH (client_company,client_description,client_keywords) AGAINST ('test') > 0 
AND CONCAT(client_address,' ',client_city,', ',client_state,' ',client_zip) LIKE '%brooklyn%' 
LIMIT 10; 

EDIT:

Voici l'info de table:

CREATE TABLE `tb_clients` (
    `client_id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `client_company` varchar(254) NOT NULL, 
    `client_address` varchar(254) NOT NULL, 
    `client_street` varchar(254) NOT NULL, 
    `client_city` varchar(254) NOT NULL, 
    `client_state` varchar(254) NOT NULL, 
    `client_zip` varchar(45) NOT NULL, 
    `client_email` varchar(254) NOT NULL, 
    `client_website` varchar(254) NOT NULL, 
    `client_description` text NOT NULL, 
    `client_keywords` text NOT NULL, 
    PRIMARY KEY (`client_id`) USING BTREE, 
    FULLTEXT KEY `client_company` (`client_company`,`client_description`,`client_keywords`) 
) ENGINE=MyISAM AUTO_INCREMENT=68347 DEFAULT CHARSET=latin1; 

ET

CREATE TABLE `tb_clients_phone_fax` (
    `client_phone_fax_id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `client_id` int(11) unsigned NOT NULL, 
    `client_phone_1` varchar(45) NOT NULL, 
    `client_phone_2` varchar(45) NOT NULL, 
    `client_phone_3` varchar(45) NOT NULL, 
    `client_fax_1` varchar(45) NOT NULL, 
    `client_fax_2` varchar(45) NOT NULL, 
    `client_fax_3` varchar(45) NOT NULL, 
    PRIMARY KEY (`client_phone_fax_id`) USING BTREE 
) ENGINE=MyISAM AUTO_INCREMENT=33944 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC; 
+0

Pouvons-nous supposer que '% brooklyn%' représente un paramètre de recherche? – ChaosPandion

+1

Il serait utile d'afficher les types de données de chaque champ et les champs qui sont des indices. – philfreo

+0

oui,% brooklyn% 'représente un paramètre de recherche. – mike

Répondre

2

tb_clients.client_id et tb_clients_phone_fax.client_id devraient être indexés.

Mais le principal problème semble être les deux comparaisons de chaînes, MATCH et le LIKE avec le CONCAT. Es-tu sûr qu'il n'y a pas d'autre guerre autour d'elle? comme, en évitant de concaténer tous les champs d'adresse avant de faire l'instruction LIKE?

MISE À JOUR: Il semble que tb_clients_phone_fax.client_id n'est pas indexé, cela améliorerait les performances s'il est indexé.

+0

Il a couru en fait assez rapidement avant ajouté: tb_clients.client_id = tb_clients_phone_fax.client_id Je viens d'essayer de prendre le CONCAT et il fonctionne encore assez lent ... – mike

+0

tb_clients_phone_fax.client_id est pas indexé, indexer! – albertein

+0

ok, je vais sûrement essayer cela demain quand de retour au travail – mike

1

Sans voir le schéma de la table, c'est difficile à dire, mais je suppose que c'est parce que vous ne cherchez pas d'indices. Essayez le manuel MySQL pour les recherches en texte intégral: http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html Pour une meilleure réponse, vous aurez probablement besoin de poster votre schéma et vos indices.

1

Vous devriez commencer par faire en sorte que tb_clients a un index pour client_id et tb_clients_phone_fax a un index sur client_id. Ensuite, essayez d'ajouter des index pour client-entreprise, description-client, client-mots-clés.

Cependant, je suis prêt à parier que le ralentissement majeur vient pour la comparaison que vous faites sur le client_address,client_city,client_state,client_zip concaténé, alors essayez de trouver un autre moyen de faire cette comparaison sans une concaténation. Pouvez-vous ajouter un champ à la table qui contient les données de ces éléments concaténés, puis simplement comparer sur ce champ? (Laide je sais)

1

Ne connaissant rien de votre situation, ma première réflexion, outre l'indexation mentionnée, est la suivante: combien y a-t-il de lignes dans ces deux tables? L'un d'entre eux est seulement quelques milliers alors que l'autre est dix millions? En supposant que les performances de votre requête ne sont pas dues à un grand ensemble de données, alors:

Comme d'autres l'ont dit, vérifiez que vos colonnes sont indexées. De même, pourquoi fulltext indexe-t-il les colonnes que vous concaténez et utilise ensuite un second MATCH() AGAINST() dans votre requête au lieu de CONCAT() et LIKE?

Qu'en est-il de la mise à jour de votre code pour vérifier, disons, un motif de code postal, puis écrire votre requête en conséquence? Ou, disons, si ce n'est pas un motif de code postal, alors ne vous embêtez pas à chercher dans cette colonne. Une chose qui a bien fonctionné pour moi dans les situations de volume élevé où une table entière (grande) doit être recherchée est de créer une colonne qui contient la concaténation de la table entière. Je mets un index de fulltext sur cette colonne et utilise MATCH() AGAINST() et ai des temps de requête très rapides - ainsi dans mon expérience, l'indexation de plein texte fait le travail.Maintenant, si vous avez une très grande table, alors rejoindre en temps réel peut devenir inacceptable. À ce stade, vous avez quelques options, mais toutes sont une variante de faire cela en arrière-plan et de stocker ce résultat pour le bénéfice de l'expérience de l'utilisateur final.

+0

Eh bien, les deux tables contiennent le même nombre de lignes. Quelque chose comme 30k ... Le tout sur la vérification d'un code postal serait bien, mais nous avons des clients dans différents pays qui ont des codes zip très différents: \ - la planification pour vérifier l'indice de demain ... – mike

0

Je voudrais créer une vue pour la table tb_clients qui avait une colonne «fausse» qui contiendrait vos informations concaténées.

De plus, j'indexerais les colonnes d'id précédemment mentionnées.

alors vous devez utiliser la même requête de base, en remplacement de la vue de la table et en omettant la concat (puisqu'il est fait par la vue comme une colonne globale)

Je suis à 5 minutes de congé et je Je ne peux pas entrer dans beaucoup de détails. Si vous avez besoin de code, par exemple SQL, laissez-moi savoir et je vais mettre quelque chose ensemble pour vous plus tard ce soir ou demain.

0

Un très petit conseil:

CONCAT(client_address,' ',client_city,', ',client_state,' ',client_zip) LIKE '%brooklyn%' 

est toute CONCAT nécessaire? Avez-vous beaucoup de clients avec brooklyn à l'intérieur de leur état ou code postal?

(En outre, vous vous rendez compte que cela correspondrait à une adresse comme

1342 Brooklyn Rue
Foobar, MI 98765

Est-ce intentionnel?)

+0

bon point, je n'ai même pas pense à ça ... – mike

1

La première étape lors du débogage lent requêtes est en cours d'exécution EXPLAIN SELECT ... et en regardant ce que MySQL est en train de faire, au lieu de deviner. Mais oui, il ressemble à un indice sur tb_clients_phone_fax.client_id aiderait, comme d'autres l'ont dit.

Questions connexes