Quelles sont les erreurs courantes de développement de base de données commises par les développeurs d'applications?
Quelles sont les erreurs courantes de développement de base de données commises par les développeurs d'applications?
Réponses:
1. Ne pas utiliser d'indices appropriés
C'est relativement facile mais ça arrive tout le temps. Les clés étrangères doivent avoir des index dessus. 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 - ce qui signifie que toutes les clés étrangères sont garanties pour pointer vers une entité qui existe - vous devez l'utiliser.
Il est assez fréquent de voir cet échec sur les bases de données MySQL. Je ne crois pas que MyISAM le supporte. InnoDB le fait. Vous trouverez des personnes qui utilisent MyISAM ou celles 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 l'extérieur qui sont (ostensiblement) uniques. Les exemples courants sont les codes de produit, les codes d'État à deux lettres (États-Unis), les numéros de sécurité sociale, etc. Les clés primaires de substitution ou techniques 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 devez toujours utiliser des clés de substitution. Ce problème est apparu dans ces questions:
Il s'agit d'un sujet quelque peu controversé sur lequel vous n'obtiendrez pas d'accord universel. Bien que vous puissiez trouver certaines personnes, qui pensent que les clés naturelles sont OK dans certaines situations, vous ne trouverez aucune critique des clés de substitution autre que 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. Rédaction de requêtes nécessitant DISTINCT
de travailler
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 ...
C'est un peu un raccourci pour vous assurer de ne pas renvoyer de lignes en double et d'obtenir ainsi des objets en double. Vous verrez parfois des gens faire cela aussi. Si vous le voyez trop, c'est un vrai drapeau rouge. Pas çaDISTINCT
n'est pas mauvais ou n'a pas d'applications valides. C'est le cas (sur les deux points), mais ce n'est pas un substitut ou un intervalle pour écrire des requêtes correctes.
De Pourquoi je déteste DISTINCT :
À mon avis, les choses commencent à mal tourner quand un développeur crée une requête substantielle, joint des tables et soudain, il se rend compte qu'il semble qu'il obtienne des lignes en double (ou même plus) et sa réponse immédiate ... sa «solution» à ce «problème» est de jeter sur le mot-clé DISTINCT et POOF tous ses problèmes disparaissent.
5. Favoriser l'agrégation plutôt que les jointures
Une autre erreur courante des développeurs d'applications de base de données est de ne pas réaliser combien d'agrégation plus coûteuse (c'est-à-dire la GROUP BY
clause) peut être comparée aux jointures.
Pour vous donner une idée de l'étendue de ce phénomène, j'ai écrit plusieurs fois sur ce sujet ici et j'ai été beaucoup moins bien noté. Par exemple:
De l' instruction SQL - «rejoindre» vs «grouper 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 join que j'ai proposée est vingt fois plus rapide que la version agrégée.
6. Ne pas simplifier les requêtes complexes via les 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 Party générique pour CRM. Il s'agit d'une technique de modélisation extrêmement puissante et flexible, mais elle peut conduire à de nombreuses jointures. Dans ce modèle, il y avait:
Exemple:
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 vous fournissez cette vue d'aide:
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 soudain, vous avez une vue très simple des données que vous voulez, mais sur un modèle de données très flexible.
7. Entrée non désinfectante
C'est énorme. Maintenant, j'aime 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 l' histoire des petites tables Bobby .
Les données fournies par l'utilisateur via des URL, des données de formulaire et des cookies doivent toujours être traitées comme hostiles et nettoyées. Assurez-vous d'obtenir ce que vous attendez.
8. Ne pas utiliser de déclarations 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 WHERE
clauses, 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 plateforme.
J'ai vu des bases de données mises à genoux en faisant cela. Fondamentalement, chaque fois qu'une base de données moderne rencontre une nouvelle requête, elle doit la compiler. S'il 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 la possibilité de comprendre et d'optimiser en conséquence (par exemple, en épinglant la requête compilée en mémoire).
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 normalisé
La normalisation de la base de données est essentiellement 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é du 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 reviendrait à traiter l'élément de ce tableau comme une ligne distincte dans une table enfant (c'est-à-dire une relation un-à-plusieurs).
Cela est également apparu dans la meilleure méthode pour stocker une liste d'ID utilisateur :
J'ai vu dans d'autres systèmes que la liste est stockée dans un tableau PHP sérialisé.
Mais le manque de normalisation se présente sous plusieurs 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 pour une fin et non une fin en soi. Je pense que de nombreux développeurs oublient cela et commencent à traiter un "moyen" comme une "fin". Les tests unitaires en sont un excellent exemple.
J'ai déjà travaillé sur un système qui avait une énorme hiérarchie pour les clients qui ressemblait à:
Licensee -> Dealer Group -> Company -> Practice -> ...
de sorte que vous deviez joindre environ 11 tables avant de pouvoir obtenir des données significatives. C'était un bon exemple de normalisation prise trop loin.
Plus précisément, une dénormalisation minutieuse et réfléchie peut avoir d'énormes avantages en termes de performances, mais vous devez être très prudent lorsque vous effectuez cette opération.
Plus:
11. Utilisation d'arcs exclusifs
Un arc exclusif est une erreur courante lorsqu'une table est créée avec deux ou plusieurs clés étrangères où une et une seule d'entre elles peuvent être non nulles. Grosse erreur. D'une part, il devient d'autant plus difficile de maintenir l'intégrité des données. Après tout, même avec l'intégrité référentielle, rien n'empêche la définition de deux ou plusieurs de ces clés étrangères (malgré les contraintes de vérification complexes).
D' un guide pratique à la conception de bases de données relationnelles :
Nous avons fortement déconseillé la construction exclusive d'arc dans la mesure du possible, pour la bonne raison qu'ils peuvent être difficiles à écrire du code et poser plus de difficultés de maintenance.
12. Ne pas faire du tout d'analyse des performances sur les 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 agrégées ci-dessus. La version agrégée peut sembler "agréable" mais ses performances sont lamentables. Une comparaison des performances aurait dû mettre fin au débat (mais ce ne fut pas le cas), mais plus précisément: jaillir de telles opinions mal informées est en premier lieu ignorant, voire dangereux.
13. Dépendance excessive à l'égard de UNION ALL et en particulier des constructions UNION
Une UNION en termes SQL concatène simplement des ensembles de données congrus, 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 devrait être préférée dans la mesure du possible alors qu'un UNION fera implicitement un DISTINCT pour supprimer les tuples en double.
Les UNIONS, comme DISTINCT, ont leur place. Il y a des applications valides. Mais si vous vous retrouvez à en faire beaucoup, en particulier dans les sous-requêtes, vous faites probablement quelque chose de mal. Cela pourrait être un cas de mauvaise construction de requête ou d'un modèle de données mal conçu vous obligeant à faire de telles choses.
Les UNIONs, en particulier lorsqu'ils sont utilisés 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 des conditions OR dans les requêtes
Cela peut sembler inoffensif. Après tout, les ET sont OK. OU devrait être OK trop à droite? Faux. Fondamentalement, une condition ET restreint l'ensemble de données tandis qu'une condition OU le fait croître , mais pas d'une manière qui se prête à l'optimisation. Particulièrement 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
Meilleur:
... WHERE a IN (2, 5, 11)
Votre optimiseur SQL peut maintenant transformer efficacement la première requête en seconde. Mais ce n'est peut-être pas le cas. Ne le fais pas.
15. Ne pas concevoir leur modèle de données pour se prêter à des solutions performantes
C'est un point difficile à quantifier. Il est généralement observé par son effet. Si vous vous retrouvez à écrire des requêtes noueuses pour des tâches relativement simples ou que les requêtes pour trouver des informations relativement simples ne sont pas efficaces, alors vous avez probablement un mauvais modèle de données.
À certains égards, ce point résume tous les précédents, mais il s'agit plus d'un récit édifiant que faire des choses comme l'optimisation des requêtes se fait souvent en premier, alors qu'il devrait l'être en deuxième. Avant tout, vous devez vous assurer d'avoir un bon modèle de données avant d'essayer d'optimiser les performances. Comme l'a dit Knuth:
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 que si l'opération réussit, elle le fait pleinement. S'il échoue, les données restent inchangées. - Il ne devrait pas y avoir de possibilité de modifications «à moitié effectuées».
Dans l'idéal, la manière la plus simple d'y parvenir est que la conception complète du système s'efforce de prendre en charge toutes les modifications de données via des instructions INSERT / UPDATE / DELETE uniques. Dans ce cas, aucune gestion de transaction spéciale n'est nécessaire, car votre moteur de base de données doit le faire automatiquement.
Cependant, si des processus nécessitent que plusieurs instructions soient exécutées en tant qu'unité pour conserver les données dans un état cohérent, un contrôle de transaction approprié est nécessaire.
Il est également recommandé de prêter une attention particulière aux subtilités de la façon dont votre couche de connectivité de base de données et le moteur de base de données interagissent à cet égard.
17. Ne pas comprendre le paradigme «basé sur les ensembles»
Le langage SQL suit un paradigme spécifique adapté à des types spécifiques de problèmes. Malgré diverses extensions spécifiques au fournisseur, le langage a du mal à gérer les problèmes banals dans des langues comme Java, C #, Delphi, etc.
Ce manque de compréhension se manifeste de plusieurs manières.
Déterminez une répartition claire des responsabilités et efforcez-vous d'utiliser l'outil approprié pour résoudre chaque problème.
Erreurs de conception et de programmation des bases de données commises par les développeurs
Conception et utilisation égoïstes de bases de données. Les développeurs traitent souvent la base de données comme leur magasin d'objets persistant personnel sans tenir compte des besoins des autres parties prenantes dans les données. Cela s'applique également aux architectes d'applications. La mauvaise conception 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 augmenter considérablement les coûts du cycle de vie du système. Les rapports et les SIG ont tendance à être un mauvais cousin dans la conception des applications et ne sont effectués qu'après coup.
Abus de données dénormalisées. L'excès de données dénormalisées et la tentative de les conserver dans l'application est une recette pour les 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 dénormaliser.
Peur d'écrire SQL. SQL n'est pas sorcier et est en fait assez bon pour faire son travail. Les couches de mappage O / R sont assez bonnes pour effectuer 95% des requêtes qui sont simples et s'intègrent bien dans ce modèle. Parfois, SQL est la meilleure façon de faire le travail.
Politiques Dogmatic «No Stored Procedures». Peu importe si vous pensez que les procédures stockées sont mauvaises, ce type d'attitude dogmatique n'a pas sa place dans un projet logiciel.
Ne pas comprendre la conception de la base de données. La normalisation est votre amie et ce n'est pas sorcier. La jonction 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.
Surutilisation et / ou dépendance des procédures stockées.
Certains développeurs d'applications voient les procédures stockées comme une extension directe du code intermédiaire / frontal. Cela semble être un trait commun chez les développeurs de piles Microsoft (j'en suis un, mais j'ai grandi) et produit de nombreuses procédures stockées qui exécutent une logique métier complexe et un traitement de flux de travail. C'est beaucoup mieux fait ailleurs.
Les procédures stockées sont utiles lorsqu'il a été réellement prouvé qu'un certain facteur technique réel nécessite leur utilisation (par exemple, les performances et la sécurité).
J'ai récemment dû aider à maintenir et à améliorer une grande application de bureau Delphi dont 70% de la logique et des règles métier ont été implémentées dans 1400 procédures stockées SQL Server (le reste dans les gestionnaires d'événements de l'interface utilisateur). Ce fut un cauchemar, principalement dû à la difficulté d'introduire des tests unitaires efficaces dans TSQL, au manque d'encapsulation et aux outils médiocres (débogueurs, éditeurs).
En travaillant avec une équipe Java dans le passé, j'ai rapidement découvert que souvent l'opposé complet se vérifie dans cet environnement. Un architecte Java m'a dit un jour: "La base de données est pour les données, pas pour le code.".
De nos jours, je pense que c'est une erreur de ne pas considérer du tout les proc stockés, mais ils devraient être utilisés avec parcimonie (pas par défaut) dans des situations où ils offrent des avantages utiles (voir les autres réponses).
Problème numéro un? Ils ne testent que sur des bases de données de jouets. Ils n'ont donc aucune idée que leur SQL va ramper lorsque la base de données sera volumineuse, et quelqu'un doit venir le réparer plus tard (ce son que vous pouvez entendre est mon grincement de dents).
Ne pas utiliser d'index.
Mauvaise performance causée par des sous-requêtes corrélées
La plupart du temps, vous voulez é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 l'application de la condition contenant la sous-requête corrélée.
Pardonnez l'exemple artificiel et la syntaxe Oracle, mais disons que vous vouliez trouver tous les employés qui ont été embauchés dans l'un de vos magasins depuis la dernière fois que le magasin a réalisé moins de 10000 $ 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. Une façon 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 dans la clause from est désormais une vue en ligne (là encore 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. Il fonctionnerait mieux 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 que de nombreux magasins n'avaient pas d'employés) et que 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 être plus performante qu'une alternative.
J'ai vu des développeurs juniors corréler les sous-requêtes à plusieurs reprises et cela a généralement eu un impact sévère sur les performances. Cependant, lorsque vous supprimez une sous-requête corrélée, assurez-vous de consulter le plan d'explication avant et après pour vous assurer que les performances ne sont pas moins bonnes.
Utiliser Access au lieu d'une "vraie" base de données. Il existe de nombreuses bases de données petites et même gratuites, comme SQL Express , MySQL et SQLite, qui fonctionneront et évolueront beaucoup mieux. Les applications doivent souvent évoluer de manière inattendue.
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 65535 lignes sur les versions précédentes d'Excel).
Excel est bien adapté 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.
Je voudrais ajouter: privilégier le code "élégant" au code hautement performant. Le code qui fonctionne le mieux contre les bases de données est souvent moche aux yeux du développeur d'applications.
Croire ce non-sens sur l'optimisation prématurée. Les bases de données doivent tenir compte des performances dans la conception d'origine et dans tout développement ultérieur. La performance est de 50% de la conception de la base de données (40% est l'intégrité des données et les 10 derniers% est la sécurité) à mon avis. Les bases de données qui ne sont pas construites de bas en haut pour fonctionner fonctionneront mal une fois que les utilisateurs réels et le trafic réel seront placés contre la base de données. L'optimisation prématurée ne signifie pas aucune optimisation! Cela ne signifie pas que vous devez é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 chercher à éliminer cette dernière petite performance jusqu'à ce que vous en ayez besoin. On sait beaucoup de choses sur les meilleures performances des bases de données,
Ne pas utiliser de requêtes paramétrées. Ils sont assez pratiques pour arrêter l' injection SQL .
Il s'agit d'un exemple spécifique de non-désinfection des données d'entrée, mentionné dans une autre réponse.
Je déteste quand les développeurs utilisent des instructions select imbriquées ou même des fonctions retournent le résultat d'une instruction select dans la partie "SELECT" d'une requête.
Je suis en fait surpris de ne voir cela nulle part ailleurs ici, peut-être que je l'ai ignoré, bien que @adam ait un problème similaire indiqué.
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 d'exécuter 20001 requêtes, 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 tirer dans un environnement de développement où ils ne renvoient que quelques lignes de données et les sous-tables ne contiennent généralement qu'une petite quantité de données, mais dans un environnement de production, ce type de requête peut devenir exponentiellement coûteux car plus des données sont ajoutées aux tableaux.
Un meilleur exemple (pas nécessairement parfait) serait quelque chose comme:
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 base de données de mélanger les données ensemble, plutôt que d'effectuer une nouvelle requête sur chaque enregistrement de la table principale et je trouve 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.
Pour les bases de données SQL:
Ne pas prendre de sauvegarde avant de corriger un problème dans la base de données de production.
Utilisation de commandes DDL sur des objets stockés (comme des tables, des vues) dans des procédures stockées.
Peur d'utiliser un proc stocké ou peur d'utiliser des requêtes ORM partout où celle-ci est plus efficace / appropriée à utiliser.
Ignorer l'utilisation d'un profileur de base de données, qui peut vous dire exactement en quoi votre requête ORM est finalement convertie et donc vérifier la logique ou même le débogage lorsque vous n'utilisez pas ORM.
Ne fait pas 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 selon vos besoins. Vous devez également vous assurer que vous ne suivez pas la normalisation trop loin car cela nuirait aux performances.
Traiter la base de données comme un simple mécanisme de stockage (c.-à-d. Bibliothèque de collections glorifiées) et donc subordonnée à leur application (en ignorant les autres applications qui partagent les données)
1 - Utilisation inutile d'une fonction sur une valeur dans une clause where avec le résultat de l'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 fonctionnels aux valeurs qui en ont besoin ...
2 - Ne pas ajouter de contraintes de vérification pour garantir la validité des données. L'optimiseur de requêtes peut utiliser des contraintes et elles aident vraiment à garantir que vous pouvez faire confiance à vos invariants. Il n'y a tout simplement aucune raison de ne pas les utiliser.
3 - Ajout de colonnes non normalisées aux tables par pure paresse ou pression du temps. Les choses ne sont généralement pas conçues de cette façon, mais évoluent vers cela. Le résultat final, sans faute, est une tonne de travail essayant de nettoyer le gâchis lorsque vous êtes mordu par l'intégrité des données perdues dans les évolutions futures.
Pensez à cela, une table sans données est très bon marché à repenser. Une table avec quelques millions d'enregistrements sans intégrité ... pas si bon marché à repenser. Ainsi, faire la bonne conception lors de la création de la colonne ou du tableau est amorti en pique.
4 - pas tellement sur 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 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 SQL dans du texte d'une manière qui soit réellement lisible par votre collègue programmeur.
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 en faisant simplement un peu de profilage (pour voir quelles tables étaient souvent 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 des données comme la peste. Certaines personnes préconisent qu'un peu de duplication ne nuira pas et améliorera les performances. Hé, je ne dis pas que vous devez torturer votre schéma en troisième forme normale, jusqu'à ce qu'il soit si abstrait que même les DBA ne savent pas ce qui se passe. Comprenez simplement que chaque fois que vous dupliquez un ensemble de noms, de codes postaux ou de codes d'expédition, les copies ne seront plus synchronisées les unes avec les autres. Cela va arriver. Et puis vous vous donnerez un coup de pied en exécutant le script de maintenance hebdomadaire.
Et 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 vous dire pratiquement ce qu'il fait, même sans commentaires. Vous vous remercierez dans six mois, lorsque vous devrez faire l'entretien sur les tables. "SELECT account_number, billing_date FROM national_accounts"
est infiniment plus facile à utiliser que "SELECT ACCNTNBR, BILLDAT FROM NTNLACCTS".
L'erreur la plus courante 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 un gâchis et inefficace et difficile à nettoyer ou à simplifier plus tard.
a) Valeurs de requête de codage en dur dans la chaîne
b) Placement du code de requête de base de données dans l'action "OnButtonPress" dans une application Windows Forms
J'ai vu les deux.
Penser qu'ils sont des administrateurs de base de données et des modélisateurs / concepteurs de données lorsqu'ils n'ont aucun endoctrinement formel d'aucune sorte dans ces domaines.
Penser que leur projet ne nécessite pas de DBA parce que tout cela est facile / trivial.
Échec de la distinction correcte entre le travail qui doit être effectué dans la base de données et le travail qui doit être effectué dans l'application.
Ne pas valider les sauvegardes ou ne pas sauvegarder.
Incorporation de SQL brut dans leur code.
Voici un lien vers une vidéo intitulée « Erreurs classiques de développement de base de données et cinq façons de les surmonter » par Scott Walz
Ne pas comprendre le modèle de concurrence des bases de données et comment cela affecte le développement. Il est facile d'ajouter des index et de modifier les requêtes après coup. Cependant, les applications conçues sans tenir compte des hotspots, des conflits de ressources et du bon fonctionnement (en supposant que ce que vous venez de lire est toujours valide!) Peuvent nécessiter des modifications importantes au sein de la base de données et du niveau d'application pour être corrigées ultérieurement.
Ne pas comprendre comment un SGBD fonctionne sous le capot.
Vous ne pouvez pas conduire correctement un bâton sans comprendre comment fonctionne un embrayage. Et vous ne pouvez pas comprendre comment utiliser une base de données sans comprendre que vous écrivez vraiment dans un fichier sur votre disque dur.
Plus précisément:
Savez-vous ce qu'est un index cluster? Avez-vous pensé à cela lorsque vous avez conçu votre schéma?
Savez-vous comment utiliser correctement les index? Comment réutiliser un index? Savez-vous ce qu'est un indice de couverture?
Tellement génial, vous avez des index. Quelle est la taille d'une ligne dans votre index? Quelle sera la taille de l'indice lorsque vous aurez beaucoup de données? Est-ce que cela rentrera facilement dans la mémoire? Sinon c'est inutile comme index.
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, tu ne l'as probablement pas fait. Répare ça.
Comprenez-vous le cache de requête? Savez-vous ce qui rend une requête non cachable?
Utilisez-vous MyISAM? Si vous avez besoin d'une recherche en texte intégral, MyISAM est de toute façon de la merde. Utilisez Sphinx. Passez ensuite à Inno.