web-dev-qa-db-fra.com

Erreurs de développement de base de données commises par les développeurs d'applications

Quelles sont les erreurs courantes de développement de bases de données commises par les développeurs d'applications?

566
Charles Faiga

1. Ne pas utiliser les index appropriés

C'est relativement facile mais cela arrive tout le temps. Les clés étrangères doivent avoir des index sur elles. Si vous utilisez un champ dans un WHERE, vous devriez (probablement) avoir un index dessus. Ces index doivent souvent couvrir plusieurs colonnes en fonction des requêtes que vous devez exécuter.

2. Ne pas appliquer l'intégrité référentielle

Votre base de données peut varier ici, mais si votre base de données prend en charge l’intégrité référentielle (c’est-à-dire que toutes les clés étrangères pointent vers une entité existante), vous devriez l’utiliser.

Il est assez courant de voir cet échec sur les bases de données MySQL. Je ne crois pas que MyISAM le supporte. InnoDB fait. Vous trouverez des personnes qui utilisent MyISAM ou qui utilisent InnoDB mais ne l'utilisent pas de toute façon.

Plus ici:

3. Utilisation de clés primaires naturelles plutôt que de substitution (techniques)

Les clés naturelles sont des clés basées sur des données significatives de manière externe qui sont (apparemment) uniques. Des exemples courants sont les codes de produits, les codes d’état à deux lettres (US), les numéros de sécurité sociale, etc. Les clés primaires techniques ou de substitution sont celles qui n'ont absolument aucune signification en dehors du système. Ils sont inventés uniquement pour identifier l'entité et sont généralement des champs auto-incrémentés (SQL Server, MySQL, autres) ou des séquences (notamment Oracle).

À mon avis, vous devriez toujours utiliser des clés de substitution. Ce problème a été soulevé dans les questions suivantes:

C’est un sujet quelque peu controversé sur lequel vous n’obtiendrez pas d’accord universel. Vous trouverez peut-être certaines personnes qui pensent que les clés naturelles sont acceptables dans certaines situations, mais vous ne trouverez aucune critique à propos des clés de substitution si ce n’est sans doute inutile. C'est un petit inconvénient si vous me demandez.

N'oubliez pas que même les pays peuvent cesser d'exister (par exemple, la Yougoslavie).

4. Écrire des requêtes qui nécessitent le fonctionnement de DISTINCT

Vous le voyez souvent dans les requêtes générées par ORM. Regardez la sortie du journal d'Hibernate et vous verrez toutes les requêtes commencer par:

SELECT DISTINCT ...

Il s’agit d’un raccourci pour éviter de renvoyer des lignes en double et d’obtenir des objets en double. Vous verrez parfois des gens faire cela aussi. Si vous le voyez trop, c'est un véritable drapeau rouge. Non pas que DISTINCT soit mauvais ou n’ait pas d’applications valides. C'est le cas (sur les deux plans), mais ce n'est pas un substitut ou un palliatif pour écrire des requêtes correctes.

De pourquoi je déteste DISTINCT :

À mon avis, les choses commencent à mal tourner lorsqu'un développeur construit une requête substantielle en joignant des tables, et qu'il se rend compte tout à coup qu'il semble comme s'il obtenait des doublons (ou même davantage) de lignes et sa réponse immédiate ... sa "solution" à ce "problème" consiste à ajouter le mot clé DISTINCT et POOF tous ses problèmes s'en vont.

5. Favoriser l'agrégation par rapport aux jointures

Une autre erreur courante des développeurs d'applications de base de données est de ne pas se rendre compte à quel point une agrégation plus coûteuse (c'est-à-dire la clause GROUP BY) peut être comparée à des jointures.

Pour vous donner une idée de l’ampleur de ce phénomène, j’ai écrit plusieurs fois sur ce sujet et m’avoir beaucoup critiqué pour cela. Par exemple:

De instruction SQL - "rejoindre" vs "grouper par et avoir" :

Première requête:

SELECT userid
FROM userrole
WHERE roleid IN (1, 2, 3)
GROUP by userid
HAVING COUNT(1) = 3

Temps de requête: 0.312 s

Deuxième requête:

SELECT t1.userid
FROM userrole t1
JOIN userrole t2 ON t1.userid = t2.userid AND t2.roleid = 2
JOIN userrole t3 ON t2.userid = t3.userid AND t3.roleid = 3
AND t1.roleid = 1

Temps de requête: 0.016 s

C'est vrai. La version de jointure que j'ai proposée est vingt fois plus rapide que la version agrégée.

6. Ne pas simplifier les requêtes complexes à travers des vues

Tous les fournisseurs de bases de données ne prennent pas en charge les vues, mais pour ceux qui le font, ils peuvent grandement simplifier les requêtes s’ils sont utilisés judicieusement. Par exemple, sur un projet, j’ai utilisé un modèle générique de parti pour le CRM. C'est une technique de modélisation extrêmement puissante et flexible, mais qui peut conduire à de nombreuses jointures. Dans ce modèle, il y avait:

  • Parti : personnes et organisations;
  • Rôle du parti : choses que ces partis ont faites, par exemple, Employé et Employeur;
  • Relation de rôle entre partis : comment ces rôles sont-ils liés les uns aux autres.

Exemple:

  • Ted est une personne, étant un sous-type de parti;
  • Ted a plusieurs rôles, dont celui d’employé;
  • Intel est une organisation, étant un sous-type d’une partie;
  • Intel a plusieurs rôles, dont celui d’employeur;
  • Intel emploie Ted, ce qui signifie qu'il existe une relation entre leurs rôles respectifs.

Il y a donc cinq tables jointes pour relier Ted à son employeur. Vous supposez que tous les employés sont des personnes (pas des organisations) et fournissez cette vue d'assistance:

CREATE VIEW vw_employee AS
SELECT p.title, p.given_names, p.surname, p.date_of_birth, p2.party_name employer_name
FROM person p
JOIN party py ON py.id = p.id
JOIN party_role child ON p.id = child.party_id
JOIN party_role_relationship prr ON child.id = prr.child_id AND prr.type = 'EMPLOYMENT'
JOIN party_role parent ON parent.id = prr.parent_id = parent.id
JOIN party p2 ON parent.party_id = p2.id

Et du coup, vous avez une vue très simple des données que vous souhaitez, mais sur un modèle de données très flexible.

7. Pas d'assainissement d'entrée

C'est un énorme. Maintenant, j’aime bien PHP, mais si vous ne savez pas ce que vous faites, il est très facile de créer des sites vulnérables aux attaques. Rien ne résume mieux que le histoire de Little Bobby Tables .

Les données fournies par l'utilisateur sous forme d'URL, de données de formulaire et de cookies doivent toujours être traitées comme hostiles et désinfectées. Assurez-vous que vous obtenez ce que vous attendez.

8. Ne pas utiliser les instructions préparées

Les instructions préparées sont lorsque vous compilez une requête moins les données utilisées dans les insertions, les mises à jour et les clauses WHERE, puis que vous les fournissez plus tard. Par exemple:

SELECT * FROM users WHERE username = 'bob'

contre

SELECT * FROM users WHERE username = ?

ou

SELECT * FROM users WHERE username = :username

en fonction de votre plate-forme.

J'ai vu des bases de données se mettre à genoux en faisant cela. En gros, chaque fois qu'une base de données moderne rencontre une nouvelle requête, elle doit la compiler. Si elle rencontre une requête déjà vue, vous donnez à la base de données la possibilité de mettre en cache la requête compilée et le plan d'exécution. En effectuant beaucoup de requêtes, vous donnez à la base de données l’opportunité de les comprendre et de les optimiser en conséquence (par exemple, en épinglant en mémoire la requête compilée).

L'utilisation d'instructions préparées vous donnera également des statistiques significatives sur la fréquence d'utilisation de certaines requêtes.

Les instructions préparées vous protégeront également mieux contre les attaques par injection SQL.

9. Pas assez normalisant

Normalisation de la base de données est fondamentalement le processus d’optimisation de la conception de la base de données ou de la façon dont vous organisez vos données en tables.

Cette semaine, j'ai rencontré un code dans lequel quelqu'un avait implosé un tableau et l'avait inséré dans un seul champ d'une base de données. Normaliser cela consisterait à traiter l'élément de ce tableau comme une ligne distincte d'une table enfant (c'est-à-dire une relation un à plusieurs).

Ceci est également apparu dans Meilleure méthode pour stocker une liste d’ID utilisateurs :

J'ai vu dans d'autres systèmes que la liste était stockée dans un tableau sérialisé PHP.

Mais le manque de normalisation prend de nombreuses formes.

Plus:

10. Normaliser trop

Cela peut sembler une contradiction avec le point précédent, mais la normalisation, comme beaucoup de choses, est un outil. C’est un moyen de parvenir à une fin et non une fin en soi. Je pense que beaucoup de développeurs l'oublient et commencent à traiter un "moyen" comme une "fin". Les tests unitaires en sont un excellent exemple.

Une fois, j'ai travaillé sur un système qui avait une énorme hiérarchie pour les clients:

Licensee ->  Dealer Group -> Company -> Practice -> ...

de telle sorte que vous deviez réunir environ 11 tables avant de pouvoir obtenir des données utiles. C'était un bon exemple de normalisation prise trop loin.

Plus précisément, une dénormalisation prudente et réfléchie peut avoir d’énormes avantages en termes de performances, mais vous devez être très prudent lorsque vous le faites.

Plus:

11. Utilisation d'arcs exclusifs

Un arc exclusif est une erreur courante dans laquelle une table est créée avec deux clés étrangères ou plus, une et une seule d'entre elles pouvant être non nulles. Grosse erreur. D'une part, il devient beaucoup plus difficile de maintenir l'intégrité des données. Après tout, même avec une intégrité référentielle, rien n’empêche la définition de deux ou plusieurs de ces clés étrangères (nonobstant les contraintes de contrôle complexes).

De Guide pratique de la conception de bases de données relationnelles :

Nous avons vivement déconseillé, dans la mesure du possible, de construire des arcs exclusifs, pour la bonne raison qu'ils peuvent être difficiles à écrire du code et poser davantage de problèmes de maintenance.

12. Ne pas du tout analyser les performances des requêtes

Le pragmatisme règne en maître, en particulier dans le monde des bases de données. Si vous vous en tenez aux principes au point qu'ils sont devenus un dogme, vous avez probablement commis des erreurs. Prenons l'exemple des requêtes d'agrégats présentées ci-dessus. La version agrégée peut avoir l’air "sympa" mais ses performances sont lamentables. Une comparaison des performances aurait dû mettre fin au débat (mais ce n’était pas le cas), mais plus important encore: émettre des points de vue aussi mal informés en premier lieu est ignorant, voire dangereux.

13. Dépendance excessive sur les constructions UNION ALL et en particulier UNION

Une UNION en termes SQL concatène simplement des ensembles de données congruents, ce qui signifie qu'ils ont le même type et le même nombre de colonnes. La différence entre eux est que UNION ALL est une simple concaténation et doit être privilégiée dans la mesure du possible, alors qu’UNION fera implicitement un DISTINCT pour éliminer les tuples en double.

Les syndicats, comme DISTINCT, ont leur place. Il y a des applications valides. Mais si vous vous trouvez souvent à en faire beaucoup, en particulier dans les sous-requêtes, vous faites probablement quelque chose de mal. Cela peut être dû à une construction de requête médiocre ou à un modèle de données mal conçu vous obligeant à faire de telles choses.

Les unités UNION, en particulier lorsqu'elles sont utilisées dans des jointures ou des sous-requêtes dépendantes, peuvent paralyser une base de données. Essayez de les éviter autant que possible.

14. Utilisation de OR conditions dans les requêtes

Cela peut sembler inoffensif. Après tout, les ET sont OK. OR devrait être OK aussi correct? Faux. Fondamentalement, une condition AND restreint le jeu de données alors qu'une condition OR se développe mais pas d'une manière qui se prête à l'optimisation. En particulier lorsque les différentes conditions OR peuvent se croiser, forçant ainsi l'optimiseur à effectuer efficacement une opération DISTINCT sur le résultat.

Mauvais:

... WHERE a = 2 OR a = 5 OR a = 11

Mieux:

... WHERE a IN (2, 5, 11)

Votre optimiseur SQL peut maintenant transformer efficacement la première requête en une seconde. Mais ça pourrait ne pas être le cas. Juste ne le fais pas.

15. Ne pas concevoir leur modèle de données pour se prêter à des solutions hautement performantes

C'est un point difficile à quantifier. Il est généralement observé par son effet. Si vous vous trouvez en train d'écrire des requêtes épineuses pour des tâches relativement simples ou que des requêtes pour trouver des informations relativement simples ne sont pas efficaces, alors vous avez probablement un modèle de données médiocre.

À certains égards, ce point résume toutes les précédentes, mais il s’agit plutôt d’un récit édifiant que l’optimisation des requêtes est souvent effectuée en premier lieu alors qu’elle devrait être effectuée en second lieu. Avant tout, vous devez vous assurer que vous disposez d'un bon modèle de données avant d'essayer d'optimiser les performances. Comme Knuth a dit:

L'optimisation prématurée est la racine de tout Mal

16. Utilisation incorrecte des transactions de base de données

Toutes les modifications de données pour un processus spécifique doivent être atomiques. C'est à dire. Si l'opération réussit, elle le fait pleinement. Si cela échoue, les données restent inchangées. - Il ne devrait y avoir aucune possibilité de changements "à moitié faits".

Idéalement, le moyen le plus simple d'y parvenir est que l'ensemble de la conception du système s'efforce de prendre en charge toutes les modifications de données à l'aide d'instructions INSERT/UPDATE/DELETE uniques. Dans ce cas, aucun traitement de transaction particulier n'est nécessaire, car votre moteur de base de données doit le faire automatiquement.

Toutefois, si un processus nécessite que plusieurs instructions soient exécutées comme une unité pour conserver les données dans un état cohérent, un contrôle des transactions approprié est nécessaire.

  • Commencez une transaction avant la première déclaration.
  • Commettez la transaction après la dernière instruction.
  • En cas d'erreur, annulez la transaction. Et très NB! N'oubliez pas de sauter/abandonner toutes les instructions qui suivent après l'erreur.

Il est également recommandé de porter une attention particulière aux subtilités de la manière dont votre couche de connectivité de base de données et votre moteur de base de données interagissent à cet égard.

17. Ne pas comprendre le paradigme 'set-based'

Le langage SQL suit un paradigme spécifique adapté à des types de problèmes spécifiques. En dépit de diverses extensions spécifiques aux fournisseurs, le langage a du mal à résoudre des problèmes triviaux dans des langages comme Java, C #, Delphi, etc.

Ce manque de compréhension se manifeste de plusieurs manières.

  • Imposer de manière inappropriée trop de logique procédurale ou impérative à la base de données.
  • Utilisation inappropriée ou excessive de curseurs. Surtout quand une seule requête suffirait.
  • De manière incorrecte, en supposant que les déclencheurs se déclenchent une fois par ligne dans les mises à jour multi-lignes.

Déterminez clairement le partage des responsabilités et efforcez-vous d'utiliser l'outil approprié pour résoudre chaque problème.

1003
cletus

Principales erreurs de conception et de programmation commises par les développeurs

  • Conception et utilisation égoïstes de la base de données. Les développeurs traitent souvent la base de données comme un magasin d'objets persistant personnel sans prendre en compte les besoins des autres utilisateurs des données. Ceci s'applique également aux architectes d'applications. La conception médiocre de la base de données et l'intégrité des données compliquent la tâche des tiers travaillant avec les données et peuvent considérablement augmenter les coûts du cycle de vie du système. Les rapports et les systèmes d'information de gestion ont tendance à être un cousin pauvre dans la conception des applications et à ne le faire qu'après coup.

  • Abuser de données dénormalisées. Exagérer les données dénormalisées et essayer de les conserver dans l'application est une recette pour des problèmes d'intégrité des données. Utilisez la dénormalisation avec parcimonie. Ne pas vouloir ajouter une jointure à une requête n'est pas une excuse pour la dénormalisation.

  • Peur d'écrire du SQL. Le SQL n'est pas sorcier, il est plutôt bon à faire son travail. Les couches de mappage O/R sont assez efficaces pour effectuer les 95% de requêtes simples et bien adaptées à ce modèle. Parfois, SQL est la meilleure façon de faire le travail.

  • Politiques dogmatiques "Pas de procédures stockées". Que vous pensiez ou non que les procédures stockées sont diaboliques, ce type d'attitude dogmatique n'a pas sa place dans un projet logiciel.

  • Impossible de comprendre la conception de la base de données. La normalisation est votre ami et c'est pas la science de la fusée. L'adhésion et la cardinalité sont des concepts assez simples - si vous 'êtes impliqué dans le développement d'applications de base de données, il n'y a vraiment aucune excuse pour ne pas les comprendre.

  1. Ne pas utiliser le contrôle de version sur le schéma de base de données
  2. Travailler directement contre une base de données en direct
  3. Ne pas lire et comprendre des concepts de base de données plus avancés (index, index clusterisés, contraintes, vues matérialisées, etc.)
  4. Échec du test d'évolutivité ... les données de test de seulement 3 ou 4 lignes ne vous donneront jamais une image réelle des performances réelles.
80
Rad

Utilisation excessive et/ou dépendance à l'égard de procédures stockées.

Certains développeurs d'applications considèrent les procédures stockées comme une extension directe du code frontal/de niveau intermédiaire. Cela semble être un trait commun chez les développeurs de piles Microsoft (j'en suis un, mais j'en suis devenu plus grand) et produit de nombreuses procédures stockées qui exécutent une logique métier et un traitement de flux de travail complexes. C'est beaucoup mieux fait ailleurs.

Les procédures stockées sont utiles lorsqu'il a été prouvé que certains facteurs techniques réels nécessitaient leur utilisation (performances et sécurité, par exemple). Par exemple, conserver l'agrégation/le filtrage de grands ensembles de données "à proximité des données".

J'ai récemment eu à contribuer à la maintenance et à l'amélioration d'une grande application de bureau Delphi dont 70% de la logique métier et des règles étaient implémentées dans 1400 procédures stockées SQL Server (le reste sous forme de gestionnaires d'événements UI). C'était un cauchemar, principalement en raison de la difficulté d'introduire des tests unitaires efficaces dans TSQL, du manque d'encapsulation et de la médiocrité des outils (débogueurs, éditeurs).

Travaillant avec une équipe Java dans le passé, j'ai rapidement compris que l'inverse se produit souvent dans cet environnement. Un architecte Java m'a dit un jour: "La base de données est pour les données, pas le code.".

Ces jours-ci, je pense que c'est une erreur de ne pas prendre en compte les processus stockés, mais ils doivent être utilisés avec parcimonie (et non par défaut) dans des situations où ils offrent des avantages utiles (voir les autres réponses).

46
Ash

Le problème numéro un? Ils testent uniquement sur des bases de données de jouets. Ils ne savent donc pas que leur code SQL va s’exploiter lorsque la base de données devient importante et que quelqu'un doit venir la réparer plus tard (ce son que vous pouvez entendre m’appelle grincer des dents).

41
Bob Moore

Ne pas utiliser les index.

31

Mauvaises performances causées par des sous-requêtes corrélées

La plupart du temps, vous souhaitez éviter les sous-requêtes corrélées. Une sous-requête est corrélée si, dans la sous-requête, il existe une référence à une colonne de la requête externe. Lorsque cela se produit, la sous-requête est exécutée au moins une fois pour chaque ligne renvoyée et peut être exécutée plusieurs fois si d'autres conditions sont appliquées après la condition contenant la sous-requête corrélée.

Pardonnez l'exemple artificiel et la syntaxe Oracle, mais supposons que vous vouliez trouver tous les employés embauchés dans l'un de vos magasins depuis la dernière fois que le magasin a réalisé moins de 10 000 dollars de ventes en une journée.

select e.first_name, e.last_name
from employee e
where e.start_date > 
        (select max(ds.transaction_date)
         from daily_sales ds
         where ds.store_id = e.store_id and
               ds.total < 10000)

La sous-requête dans cet exemple est corrélée à la requête externe par le store_id et serait exécutée pour chaque employé de votre système. L'une des façons d'optimiser cette requête consiste à déplacer la sous-requête vers une vue en ligne.

select e.first_name, e.last_name
from employee e,
     (select ds.store_id,
             max(s.transaction_date) transaction_date
      from daily_sales ds
      where ds.total < 10000
      group by s.store_id) dsx
where e.store_id = dsx.store_id and
      e.start_date > dsx.transaction_date

Dans cet exemple, la requête de la clause from est maintenant une vue intégrée (encore une fois une syntaxe spécifique à Oracle) et n'est exécutée qu'une seule fois. Selon votre modèle de données, cette requête s'exécutera probablement beaucoup plus rapidement. Cela donnerait de meilleurs résultats que la première requête à mesure que le nombre d'employés augmentait. La première requête pourrait en fait mieux fonctionner s'il y avait peu d'employés et de nombreux magasins (et peut-être même aucun magasin) et si la table daily_sales était indexée sur store_id. Ce n'est pas un scénario probable mais montre comment une requête corrélée pourrait éventuellement mieux fonctionner qu'une alternative.

J'ai déjà vu plusieurs fois des développeurs juniors corréler des sous-requêtes, ce qui a généralement eu un impact important sur les performances. Cependant, lorsque vous supprimez une sous-requête corrélée, veillez à vous reporter à expliquer le plan avant et après pour vous assurer que vous n'empilerez pas les performances.

28
adam

Dans mon expérience:
Ne pas communiquer avec des administrateurs de base de données expérimentés.

21
Kb.

Utiliser Access au lieu d'une "vraie" base de données. Il existe de nombreuses petites bases de données, voire gratuites, telles que SQL Express , MySQL , et SQLite qui fonctionneront et s’échelonneront beaucoup mieux. Les applications doivent souvent évoluer de manière inattendue.

17
Nathan Voxland

Oublier de mettre en place des relations entre les tables. Je me souviens d’avoir dû mettre de l'ordre dans tout ça quand j'ai commencé à travailler pour mon employeur actuel.

16
TheTXI

J'aimerais ajouter: Favoriser le code "élégant" par rapport au code très performant. Le code qui fonctionne le mieux contre les bases de données est souvent moche pour le développeur d'applications.

Croire ce non-sens sur l'optimisation prématurée. Les bases de données doivent prendre en compte les performances dans la conception d'origine et dans tout développement ultérieur. Les performances représentent 50% de la conception de la base de données (40% correspond à l'intégrité des données et les 10% restants à la sécurité) à mon avis. Les bases de données qui ne sont pas conçues pour fonctionner correctement fonctionneront mal une fois que les utilisateurs réels et le trafic réel auront été placés sur la base de données. Optimisation prématurée ne veut pas dire aucune optimisation! Cela ne signifie pas que vous devriez écrire du code qui fonctionnera presque toujours mal parce que vous le trouverez plus facile (curseurs, par exemple, qui ne devraient jamais être autorisés dans une base de données de production sauf si tout le reste a échoué). Cela signifie que vous n'avez pas besoin de penser à tirer parti de ces dernières performances jusqu'à ce que vous en ayez besoin. On sait beaucoup de choses sur ce qui fonctionnera mieux avec les bases de données; ignorer cela dans la conception et le développement est au mieux à courte vue.

14
HLGEM

Utiliser Excel pour stocker (d’énormes quantités) de données.

J'ai vu des entreprises détenir des milliers de lignes et utiliser plusieurs feuilles de calcul (en raison de la limite de lignes de 65535 par rapport aux versions précédentes d'Excel).


Excel convient bien aux rapports, à la présentation des données et à d'autres tâches, mais ne doit pas être traité comme une base de données.

14
ML--

Ne pas utiliser les requêtes paramétrées. Ils sont assez pratiques pour arrêter Injection SQL .

Ceci est un exemple spécifique de non désinfection des données d'entrée, mentionné dans une autre réponse.

13
Ash

Je déteste quand les développeurs utilisent des instructions select imbriquées ou même que les fonctions renvoient le résultat d'une instruction select à l'intérieur de la partie "SELECT" d'une requête.

En fait, je suis surpris de ne pas voir cela nulle part ailleurs ici. Peut-être l'ai-je négligé, bien que @adam ait signalé un problème similaire.

Exemple:

SELECT
    (SELECT TOP 1 SomeValue FROM SomeTable WHERE SomeDate = c.Date ORDER BY SomeValue desc) As FirstVal
    ,(SELECT OtherValue FROM SomeOtherTable WHERE SomeOtherCriteria = c.Criteria) As SecondVal
FROM
    MyTable c

Dans ce scénario, si MyTable renvoie 10000 lignes, le résultat est comme si la requête venait juste d'exécuter des requêtes 20001, car elle devait exécuter la requête initiale et interroger chacune des autres tables une fois pour chaque ligne de résultat.

Les développeurs peuvent s’en sortir en travaillant dans un environnement de développement où ils ne renvoient que quelques lignes de données et où les sous-tables ne contiennent généralement qu’une petite quantité de données. Toutefois, dans un environnement de production, ce type de requête peut devenir extrêmement coûteux, car les données sont ajoutées aux tables.

Un meilleur exemple (pas nécessairement parfait) serait par exemple:

SELECT
     s.SomeValue As FirstVal
    ,o.OtherValue As SecondVal
FROM
    MyTable c
    LEFT JOIN (
        SELECT SomeDate, MAX(SomeValue) as SomeValue
        FROM SomeTable 
        GROUP BY SomeDate
     ) s ON c.Date = s.SomeDate
    LEFT JOIN SomeOtherTable o ON c.Criteria = o.SomeOtherCriteria

Cela permet aux optimiseurs de bases de données de mélanger les données ensemble, plutôt que de réinterroger chaque enregistrement de la table principale et je constate généralement que lorsque je dois corriger le code où ce problème a été créé, je finis généralement par augmenter la vitesse des requêtes de 100% ou plus tout en réduisant simultanément l'utilisation du processeur et de la mémoire.

12
CStroliaDavis

Pour les bases de données SQL:

  1. Ne pas tirer parti des INDEX CLUSTERED ou choisir la mauvaise colonne (s) pour CLUSTER.
  2. N'utilisez pas un type de données SERIAL (numérotation automatique) en tant que clé primaire pour rejoindre une clé étrangère (INT) dans une relation de table parent/enfant.
  3. Ne pas mettre à jour les statistiques sur une table lorsque de nombreux enregistrements ont été insérés ou supprimés.
  4. Ne pas réorganiser (c'est-à-dire décharger, supprimer, recréer, charger et réindexer) des tables lorsque de nombreuses lignes ont été insérées ou supprimées (certains moteurs conservent physiquement les lignes supprimées dans une table avec un indicateur de suppression).
  5. Ne pas tirer parti de FRAGMENT ON EXPRESSION (si pris en charge) sur des tables volumineuses présentant des taux de transaction élevés.
  6. Choisir le mauvais type de données pour une colonne!
  7. Ne pas choisir un nom de colonne approprié.
  8. Ne pas ajouter de nouvelles colonnes à la fin de la table.
  9. Ne pas créer les index appropriés pour prendre en charge les requêtes fréquemment utilisées.
  10. créer des index sur des colonnes avec peu de valeurs possibles et créer des index inutiles.
    ... plus à ajouter.
12
Frank R.
  • Ne pas effectuer de sauvegarde avant de résoudre un problème dans la base de données de production.

  • Utilisation de commandes DDL sur des objets stockés (tels que des tables, des vues) dans des procédures stockées.

  • Peur d'utiliser des proc stockées ou craindre d'utiliser des requêtes ORM chaque fois que celle-ci est plus efficace/appropriée à utiliser.

  • Ignorer l'utilisation d'un profileur de base de données, qui peut vous indiquer exactement en quoi votre requête ORM est convertie, et donc vérifier la logique ou même pour le débogage lorsque vous n'utilisez pas ORM.

9
WhoIsNinja

1 - Utilisation non nécessaire d'une fonction sur une valeur d'une clause where avec le résultat de cet index non utilisé.

Exemple:

where to_char(someDate,'YYYYMMDD') between :fromDate and :toDate

au lieu de

where someDate >= to_date(:fromDate,'YYYYMMDD') and someDate < to_date(:toDate,'YYYYMMDD')+1

Et dans une moindre mesure: ne pas ajouter d'index fonctionnel aux valeurs qui en ont besoin ...

2 - N'ajoutez pas de contraintes de vérification pour assurer la validité des données. Les contraintes peuvent être utilisées par l'optimiseur de requêtes, et elles aident VRAIMENT à s'assurer que vous pouvez faire confiance à vos invariants. Il n'y a aucune raison de ne pas les utiliser.

- Ajout de colonnes non normalisées à des tableaux par pure paresse ou contraintes de temps. Les choses ne sont généralement pas conçues de cette façon, mais évoluent dans ce sens. Le résultat final, sans faute, est une tonne de travail essayant de nettoyer le désordre quand vous êtes piqué par l'intégrité des données perdues dans les évolutions futures.

Pensez à cela, une table sans données est très peu coûteuse à redessiner. Une table avec quelques millions d'enregistrements sans intégrité ... pas si bon marché que de la refondre. Ainsi, la conception correcte lors de la création de la colonne ou de la table est amortie par pique.

4 - pas tellement à propos de la base de données en soi mais vraiment ennuyeux. Ne pas se soucier de la qualité du code de SQL. Le fait que votre code SQL soit exprimé en texte ne permet pas de masquer la logique dans des tas d'algorithmes de manipulation de chaînes. Il est parfaitement possible d’écrire du texte SQL sous une forme lisible par les autres programmeurs.

8
John Nilsson

Ne pas faire le bon niveau de normalisation . Vous voulez vous assurer que les données ne sont pas dupliquées et que vous divisez les données en différentes si nécessaire. Vous devez également vous assurer que vous ne suivez pas la normalisation aussi dans la mesure où cela nuirait aux performances.

8
Nathan Voxland
  • Rejeter un ORM comme Hibernate, pour des raisons telles que "c'est trop magique" ou "pas sur ma base de données".
  • S'appuyant trop lourdement sur un ORM comme Hibernate et essayant de l'installer là où ce n'est pas approprié.
8
Adam Jaskiewicz

Traiter la base de données comme un simple mécanisme de stockage (c'est-à-dire une bibliothèque de collections enrichie) et donc subordonnée à leur application (en ignorant les autres applications qui partagent les données)

8
finnw

Cela a déjà été dit, mais: index, index, index. J'ai vu tellement de cas d'applications Web d'entreprise peu performantes qui ont été corrigées simplement en faisant un peu de profilage (pour voir quelles tables étaient très touchées), puis en ajoutant un index sur ces tables. Cela ne nécessite même pas beaucoup de connaissances en écriture SQL, et le gain est énorme.

Évitez la duplication de données comme la peste. Certaines personnes préconisent qu'un petit dédoublement ne fera pas de mal et améliorera les performances. Hey, je ne dis pas que vous devez torturer votre schéma en Troisième Forme Normale, jusqu'à ce que ce soit si abstrait que même les DBA ne sachent pas ce qui se passe. Il suffit de comprendre que chaque fois que vous dupliquez un ensemble de noms, codes postaux ou codes d’expédition, les copies seront désynchronisées entre elles. Ça va arriver. Et ensuite, vous allez vous botter le pied en exécutant le script de maintenance hebdomadaire.

Enfin, utilisez une convention de dénomination claire, cohérente et intuitive. De la même manière qu'un morceau de code bien écrit doit être lisible, un bon schéma ou une requête SQL doit être lisible et pratiquement vous dire ce qu'il fait, même sans commentaires. Vous vous remercierez dans six mois, lorsque vous devrez faire l'entretien des tables. "SELECT account_number, billing_date FROM national_accounts" est infiniment plus facile à utiliser que "SELECT ACCNTNBR, BILLDAT FROM NTNLACCTS".

7
pbailey19

Ne pas exécuter une requête SELECT correspondante avant d'exécuter la requête DELETE (en particulier sur les bases de données de production)!

6
Jamol

L'erreur la plus commune que j'ai vue depuis vingt ans: ne pas planifier à l'avance. De nombreux développeurs créeront une base de données et des tables, puis modifieront et développeront continuellement les tables au fur et à mesure de la création des applications. Le résultat final est souvent désordonné et inefficace et difficile à nettoyer ou à simplifier par la suite.

5
Skatterbrainz

a) Valeurs de requête codées en dur dans la chaîne
b) Insertion du code de requête de base de données dans l'action "OnButtonPress" dans une application Windows Forms

J'ai vu les deux.

4
Benoit

Ne pas accorder suffisamment d’attention à la gestion des connexions à la base de données dans votre application. Ensuite, vous découvrez que l'application, l'ordinateur, le serveur et le réseau sont encrassés.

4
chefsmart
  1. En pensant qu'il s'agit d'administrateurs de bases de données et de modélisateurs/concepteurs de données alors qu'ils n'ont aucun endoctrinement formel d'aucune sorte dans ces domaines.

  2. En pensant que leur projet ne nécessite pas de DBA car tout cela est facile/trivial.

  3. Échec de la distinction entre le travail devant être effectué dans la base de données et le travail devant être effectué dans l'application.

  4. Ne pas valider les sauvegardes ou ne pas sauvegarder.

  5. Incorporer du SQL brut dans leur code.

4
jonesy

Voici un lien vers la vidéo intitulée " Erreurs de développement de base de données classique et cinq façons de les surmonter " par Scott Walz

3
Charles Faiga
  1. Utiliser un ORM pour effectuer des mises à jour en masse
  2. Sélection de plus de données que nécessaire. Encore une fois, généralement fait lors de l'utilisation d'un ORM
  3. Lancer des sqls en boucle.
  4. Ne pas avoir de bonnes données de test et ne pas remarquer de dégradation des performances uniquement sur des données en direct.
3
Sriram

Ne pas comprendre le modèle de concurrence des bases de données et son incidence sur le développement. Il est facile d'ajouter des index et des requêtes Tweak après coup. Cependant, les applications conçues sans tenir compte des points chauds, du conflit de ressources et du bon fonctionnement (en supposant que ce que vous venez de lire soit toujours valide!) Peuvent nécessiter des modifications importantes dans la base de données et le niveau application pour être corrigées ultérieurement.

3
Einstein

Eh bien, je dois dire que la plus grande erreur que font les développeurs d’applications est ne normalisant pas correctement la base de données.

En tant que développeur d'applications, je me rends compte de l'importance d'une structure, d'une normalisation et d'une maintenance correctes de la base de données. J'ai passé d'innombrables heures à m'instruire sur la structure et l'administration de la base de données. D'après mon expérience, chaque fois que je commence à travailler avec un développeur différent, je dois généralement restructurer la base de données entière et mettre à jour l'application en conséquence, car elle est généralement mal formée et défectueuse.

Par exemple, j'ai commencé à travailler avec un nouveau projet dans lequel le développeur m'a demandé d'implémenter Facebook Connect sur le site. J'ai ouvert la base de données pour voir ce avec quoi je devais travailler et j'ai constaté que chaque petite information relative à un utilisateur donné était entassée ne table. Il m'a fallu six heures pour écrire un script qui organiserait la table en quatre ou cinq tables séparées et deux autres pour que l'application utilise ces tables. S'il vous plaît, normalisez vos bases de données! Cela rendra tout le reste moins un casse-tête.

3
Nick Anderegg

Ne comprenant pas comment un SGBD fonctionne sous le capot.

Vous ne pouvez pas conduire correctement un bâton sans comprendre le fonctionnement d'un embrayage. Et vous ne pouvez pas comprendre comment utiliser une base de données sans comprendre que vous écrivez simplement dans un fichier sur votre disque dur.

Plus précisément:

  1. Savez-vous ce qu'est un index clusterisé? Avez-vous pensé à cela lorsque vous avez conçu votre schéma?

  2. Savez-vous comment utiliser correctement les index? Comment réutiliser un index? Savez-vous ce qu'est un indice de couverture?

  3. Tellement génial, vous avez des index. Quelle est la taille d'une rangée dans votre index? Quelle sera la taille de l'index lorsque vous avez beaucoup de données? Est-ce que ça va facilement dans la mémoire? Sinon, c'est inutile comme index.

  4. Avez-vous déjà utilisé EXPLAIN dans MySQL? Génial. Maintenant, soyez honnête avec vous-même: avez-vous compris même la moitié de ce que vous avez vu? Non, vous n'avez probablement pas. Répare ça.

  5. Comprenez-vous le cache de requêtes? Savez-vous ce qui rend une requête non cachable?

  6. Utilisez-vous MyISAM? Si vous avez besoin d'une recherche en texte intégral, MyISAM est de la merde quand même. Utilisez Sphinx. Puis passez à Inno.

3
Shane H

15 - Utilisation d’une logique de construction et d’application délirante au lieu d’une simple COALESCE.

2
jcampbell1
  • Transactions très volumineuses, insertion/mise à jour de nombreuses données, puis rechargement. En gros, il s’agit de ne pas tenir compte de l’environnement multi-utilisateurs dans lequel la base de données fonctionne.

  • Utilisation excessive de fonctions, notamment en tant que résultat dans les clauses select et where, qui provoque l'appel répétitif de la fonction pour obtenir les résultats. Je pense que cela correspond au cas général où ils essaient de travailler de la manière procédurale à laquelle ils sont plus habitués plutôt que d'utiliser pleinement le code SQL.

2
Robin

La plus grosse erreur est d'avoir une boucle dans le code en mettant à jour ou en insérant des données, alors qu'une solution basée sur un ensemble ferait l'affaire plus rapidement et beaucoup plus simplement.

2
Test223345555

Je pense que la plus grande erreur de tous les développeurs et administrateurs de base de données est de croire trop aux conventions. Ce que je veux dire par là, c'est que les conventions ne sont que des lignes directrices qui, dans la plupart des cas, fonctionneront, mais pas nécessairement. Par exemple, la normalisation et les clés étrangères sont un bon exemple. Je sais que la plupart des gens ne l’aimeront pas, mais la normalisation peut aussi entraîner de la complexité et une perte de performances. Par conséquent, s’il n’ya aucune raison de déplacer un numéro de téléphone vers une table de téléphones, ne le faites pas. il. Sur les clés étrangères, elles sont excellentes dans la plupart des cas, mais si vous essayez de créer quelque chose qui peut fonctionner tout seul si vous en avez besoin, la clé étrangère posera un problème à l'avenir, mais vous perdra également des performances. Quoi qu'il en soit, comme je suis triste, les règles et les conventions sont là pour vous guider, et elles devraient toujours être considérées, mais pas nécessairement appliquées, l'analyse de chaque cas est ce qui doit toujours être fait.

2
Oakcool

Blâmer le moteur de base de données lorsque la requête trop rapide sur votre machine de développement explose et s’étouffe dès que vous lancez du trafic vers l’application.

2
John Farrell

De nombreux développeurs ont tendance à exécuter plusieurs requêtes sur la base de données (souvent une ou deux tables), extraire les résultats et effectuer des opérations simples en Java/c/c ++ - le tout pouvant être effectué avec une seule instruction SQL.

De nombreux développeurs ne réalisent souvent pas que, dans les environnements de développement, les ordinateurs de base de données et les serveurs d'applications se trouvent sur leurs ordinateurs portables. Cependant, dans un environnement de production, les serveurs de bases de données et d'applications se trouveront sur des ordinateurs différents. Par conséquent, pour chaque requête, il existe une surcharge supplémentaire pour les données à transmettre entre le serveur d'applications et le serveur de base de données. J'ai été surpris de trouver le nombre d'appels à la base de données passés du serveur d'applications au serveur de base de données pour rendre une page à l'utilisateur!

2
sdc

Il y a une chose que je pourrais ajouter, apprendre en utilisant des fonctions analytiques telles que PARTITION BY, RANK, DENSE_RANK (pour Oracle). Ils sont absolument essentiels pour les requêtes complexes.

Il est également conseillé, dans la mesure du possible, d’inclure dans votre équipe de développement un développeur de base de données dédié, expert en SQL, modélisation de la base de données, optimisation, etc. Une telle compétence est un atout majeur.

1
softveda

Si vous utilisez la réplication (MySQL), les fonctions suivantes ne sont pas sécurisées, sauf si vous utilisez une réplication basée sur les lignes.

USER(), CURRENT_USER() (or CURRENT_USER), UUID(), VERSION(), LOAD_FILE(), and Rand()

Voir: http://dev.mysql.com/doc/refman/5.1/en/replication-features-functions.html

1
tszming

1) Mauvaise compréhension de la manière d’interagir correctement entre Java et la base de données.

2) Sur-analyse, réutilisation incorrecte ou absence de SQL

3) Ne pas utiliser les variables BIND

4) Implémentation de la logique procédurale dans Java lorsque la logique définie dans SQL dans la base de données aurait fonctionné (mieux).

5) Avoir omis de faire des tests de performance ou d'évolutivité raisonnables avant de passer en production

6) Utilisation de Crystal Reports et non définition du nom de schéma dans les rapports

7) Implémentation de SQL avec des produits cartésiens en raison de l’ignorance du plan d’exécution (avez-vous même regardé le PLAN EXPLAIN?)

1
George P. Milliken