IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

Requête SQL lente [MariaDB]


Sujet :

Requêtes MySQL

  1. #1
    Membre régulier
    Homme Profil pro
    Inscrit en
    Février 2003
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 91
    Points : 74
    Points
    74
    Par défaut Requête SQL lente
    J'essaie d'optimiser une requête SQL très lente malgré les indexes créés.
    La requête ci dessous prend 22s
    La table stat contient 724 000 lignes et stats_ip 74 000 lignes.
    Une idée pour l'optimiser ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    SELECT b.pays, COUNT(b.pays) FROM stats a, stats_ip b WHERE b.pays <> '' AND b.ip = a.ip AND a.date > now() - INTERVAL 12 month GROUP BY b.pays ORDER BY 2 DESC limit 5;
     
     
    -- Structure de la table `stats` 724 000 lignes
    CREATE TABLE `stats` (
      `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
      `page` int(11) NOT NULL DEFAULT 0,
      `ip` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
      `syst` int(11) NOT NULL DEFAULT 0,
      `navi` int(11) NOT NULL DEFAULT 0
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
     
    -- Index pour la table `stats`
    ALTER TABLE `stats`
      ADD KEY `index_date` (`date`) USING BTREE,
      ADD KEY `index_ip` (`ip`),
      ADD KEY `index_date_ip` (`date`,`ip`),
      ADD KEY `index_ip_date` (`ip`,`date`);
    COMMIT;
     
    -- Structure de la table `stats_ip` 74 000 lignes
    CREATE TABLE `stats_ip` (
      `ip` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
      `ville` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
      `region` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
      `pays` varchar(255) COLLATE utf8_unicode_ci NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=FIXED;
     
    -- Index pour la table `stats_ip`
    ALTER TABLE `stats_ip`
      ADD PRIMARY KEY (`ip`) USING BTREE,
      ADD UNIQUE KEY `index_ip_ville` (`ip`,`ville`),
      ADD UNIQUE KEY `index_ip_region` (`ip`,`region`),
      ADD UNIQUE KEY `index_ip_pays` (`ip`,`pays`);
    COMMIT;
     
     
    explain SELECT b.pays, COUNT(b.pays) FROM stats a, stats_ip b WHERE b.pays <> '' AND b.ip = a.ip AND a.date > now() - INTERVAL 12 month GROUP BY b.pays ORDER BY 2 DESC limit 5;
     
     
    1	SIMPLE	b	index	PRIMARY,index_ip_ville,index_ip_region,index_ip_pays	index_ip_pays	919	NULL	71922	Using where; Using index; Using temporary; Using filesort	
    1	SIMPLE	a	ref	index_date,index_ip,index_date_ip,index_ip_date	index_ip_date	152	tyarcaouen.b.ip	5	Using where; Using index

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 920
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 920
    Points : 51 712
    Points
    51 712
    Billets dans le blog
    6
    Par défaut
    Commencez par modéliser correctement vos tables...
    1) un VARCHAR(50) est ce qu'il y a de pire en matière de clé. Remplacez le par un entier ne dépssant pas la longueur du mot du processeur (64 bits). Votre VARCHAR(50) coute au pire 150 octets du fait que MySQL/MariaDB utilise un UTF8 imbécile avec systématiquement 3 octets par caractères, soit 1 200 octets, ce qui nécessite 19 passes dans le processeur pour lire une clé soit 38 passes pour faire une jointure...
    2) évitez la date 0 qui est une imbécilité propre à MySQL MariaDB
    3) il n'y a pas de clé primaire dans votre table "stats"

    Enfin, modifiez votre moteur pour qu'il soit en mode STRICT au niveau du SQL. Sinon, vos résultats de requêtes peuvent être incorrect. Dans le mode par défaut, les erreurs sont passées sous silence et MySQL / MariaDB renvoie n'importe quoi....

    Une fois ceci corrigé on pourra parler indexation, mais à première vue aucun des index ne satisferons votre requête !

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 377
    Points : 39 852
    Points
    39 852
    Billets dans le blog
    9
    Par défaut
    Et aussi : évitez les mots réservés SQL et les caractères spéciaux (accents, ligatures, cédilles...) dans les noms d'objets. "DATE" est un mot réservé SQL, à remplacer par date_stat par exemple.
    Ça permet de se débarrasser des quotes inversées (alt-gr + 7) dans les requêtes et ça facilite les analyses.

  4. #4
    Membre expérimenté
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    849
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 849
    Points : 1 622
    Points
    1 622
    Par défaut
    Bonjour,

    On peut essayer d'écrire la requête autrement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT b.pays, COUNT(b.pays) 
    FROM stats a, stats_ip b 
    WHERE b.pays <> '' 
    AND b.ip = a.ip 
    AND a.date > now() - INTERVAL 12 month 
    GROUP BY b.pays 
    ORDER BY 2 DESC limit 5;
    Note : le mot clé JOIN a été introduit dans la norme SQL de 1992. Vous devriez envisager de vous mettre à jour.


    Avec IN :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT b.pays, COUNT(b.pays) 
    FROM stats_ip b
    WHERE b.pays <> '' 
    AND b.ip IN (SELECT a.ip FROM stats a where a.date > now() - INTERVAL 12 month)
    GROUP BY b.pays 
    ORDER BY 2 DESC limit 5;
    Avec Exists :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT b.pays, COUNT(b.pays) 
    FROM stats_ip b
    WHERE b.pays <> '' 
    AND EXISTS (SELECT a.ip FROM stats a where b.ip = a.ip AND a.date > now() - INTERVAL 12 month )
    GROUP BY b.pays 
    ORDER BY 2 DESC limit 5;
    Le savoir est une nourriture qui exige des efforts.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 06/10/2009, 10h37
  2. Réponses: 4
    Dernier message: 11/06/2009, 17h03
  3. comment parametrer une requte sql ds ireport
    Par hamzuss dans le forum Jasper
    Réponses: 3
    Dernier message: 17/03/2009, 21h01
  4. Infopath, requete SQL lente
    Par Haziel dans le forum InfoPath
    Réponses: 2
    Dernier message: 26/06/2008, 01h04
  5. Requte Sql Avancée, question ... ? Estce possible ?
    Par plex dans le forum Administration
    Réponses: 8
    Dernier message: 14/12/2005, 16h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo