SlideShare a Scribd company logo
SQL START!
ANCONA, 28 SETTEMBRE 2012
SQL START!
ANCONA, 28 SETTEMBRE 2012
SQL Server Worst Practices
Gianluca Sartori
gianluca.sartori@sqlconsulting.it
Tecnosistemi Marche
Un GRAZIE agli sponsors
#sqlstart
Gianluca Sartori
• Independent SQL Server
consultant
• Works with SQL Server since version 7
• MCTS, MCITP, MCT
• DBA @ Scuderia Ferrari
Agenda
• Best practices o Worst practices?
• Dove posso sbagliare?
– Progettazione
– Sviluppo
– Installazione
– Amministrazione
Disclaimer:
• Non tutto è bianco o nero
• «Dipende» è la risposta migliore
Possono esistere casi limite in cui qualcuna di
queste worst practice è l’unica soluzione
possibile
Best Practices vs. Worst Practices
• Perché le Best Practices non bastano
– Sono troppe
– Non c’è tempo
– Manca l’esperienza
– Non è chiaro cosa succede se non le seguiamo
• Perché le Worst Practices servono
– Ci mostrano gli errori da non fare
– Possiamo imparare dagli errori degli altri
Worst Practices Areas
Design Development Installation Administration
Schema design
Naming
Data Types
Environment HW validation
OS configuration
SQL installation
Recovery
Security
Capacity
Performance
Monitoring
Code
Test
Schema Design
• Non normalizzare lo schema
– 1NF:
Una chiave, solo attributi atomici
– 2NF:
Ogni attributo dipende da tutta la chiave
– 3NF:
Ogni attributo dipende solo dalla chiave
«La chiave, solo la chiave, nient’altro che la
chiave, così Codd mi aiuti»
Indizi di denormalizzazione
• Dati che si ripetono  ridondanze
• Dati inconsistenti tra tabelle  anomalie
• Dati separati da «,»
• ES: john@gmail.com, john@business.com
• Dati strutturati in colonne «nota»
• Colonne con un suffisso numerico
– ES: Zona1, Zona2, Zona3 …
Schema Design Worst Practices
• Nessuna Primary Key o solo chiavi surrogate
– «Id» non è la sola chiave primaria al mondo!
• Nessuna Foreign Key
– Sono «scomode»
• Nessun vincolo CHECK
– L’applicazione garantirà la consistenza…
• Utilizzo di tipi di dato errati
– CAP, Telefono
– Date salvate come stringhe
• Utilizzo di NULL dove non necessario
• Utilizzo di valori «dummy» (es: ‘.’ , 0)
Schema Design Worst Practices
• Naming conventions inconsistenti
– Plurale o singolare?
– Italiano / Inglese
– Hungarian Notation
• tbl…
• vw...
• Nomi di oggetto o di colonna riservati
• Usare il prefisso sp_
– … meno peggio di quanto sembri!
Lookup Tables
Orders
PK order_id int
order_date datetime
FK2 customer_id int
FK1 status_id char(2)
FK3 priority_id tinyint
Order_Status
PK status_id char(2)
status_description nvarchar(50)
Customers
PK customer_id int
name varchar(100)
address varchar(50)
ZIP char(5)
city nvarchar(50)
FK2 state_id char(2)
FK1 country_id char(3)
Countries
PK country_id char(3)
description nvarchar(50)
States
PK state_id char(2)
description nvarchar(50)
Order_Priorities
PK priority_id tinyint
priority_description nvarchar(50)
Una tabella di lookup per ogni attributo
OTLT: One True Lookup Table
Orders
PK order_id int
order_date datetime
FK1 customer_id int
status_id char(2)
priority_id tinyint
Customers
PK customer_id int
name nvarchar(100)
address nvarchar(50)
ZIP char(5)
city nvarchar(50)
state_id char(2)
country_id char(3)
LookupTable
PK table_name sysname
PK lookup_code nvarchar(500)
lookup_description nvarchar(4000)
CREATE TABLE LookupTable (
table_name sysname,
lookup_code nvarchar(500),
lookup_description nvarchar(4000)
)
Una tabella di lookup per tutti gli attributi
OTLT: One True Lookup Table
• Impossibile usare Foreign Key
• Tipi di dati generici  nvarchar(?)
– Implicit Conversions
• Difficile definire vincoli CHECK
• Locking
CHECK(
CASE
WHEN lookup_code = 'states' AND lookup_code LIKE '[A-Z][A-Z]' THEN 1
WHEN lookup_code = 'priorities' AND lookup_code LIKE '[0-9]' THEN 1
WHEN lookup_code = 'countries' AND lookup_code LIKE '[0-9][0-9][0-9]' THEN 1
WHEN lookup_code = 'status' AND lookup_code LIKE '[A-Z][A-Z]' THEN 1
ELSE 0
END = 1
)
EAV: Entity, Attribute, Value
Customers
PK customer_id int
name nvarchar(100)
address nvarchar(50)
ZIP char(5)
city nvarchar(50)
state_id char(2)
country_id char(3)
AttributeNames
PK attribute_id int
PK,FK1 entity_id int
attribute_name nvarchar(128)
AttributeValues
PK,FK1 attribute_id int
PK,FK1 entity_id int
PK,FK2,FK3 id int
value nvarchar(4000)
Entities
PK entity_id int
entity_name nvarchar(128)
Orders
PK order_id int
order_date datetime
customer_id int
status_id char(2)
priority_id tinyint
EAV: Entity, Attribute, Value
• Svantaggi:
– Tipi di dato generici  ES: varchar(4000)
– No Foreign Key
– No CHECK constraints
– Accessi multipli alla stessa tabella
• Una lettura per ogni attributo
• Vantaggi
– Schema dinamico: non richiede modifiche al DB
• Replica, ambienti distribuiti
EAV: Entity, Attribute, Value
• Workaround:
– PIVOT / Crosstab
– Viste + INSTEAD OF triggers
• Alternative:
– SPARSE columns
– XML
– Key-value store databases
• Azure Table storage, Redis
– Document-oriented databases
• MongoDB, RavenDB
DEMO:
EAV Design
Development Worst Practices
Development Environment
• Non versionare lo schema del DB
• Non fornire un livello di astrazione
– Viste, Functions, Stored Procedures
• Sviluppare con privilegi di sysadmin
– In produzione non ci saranno!
Development Worst Practices
Code
• Nessuna transazione
• Nessuna gestione degli errori
– @@ERROR appartiene al passato!
• Utilizzo di livelli di isolamento errati
– NOLOCK = nessuna consistenza!
• SELECT *
• SQL dinamico con valori hardcoded
• Codice suscettibile alla SQL injection
Development Worst Practices
Test
• Non testare tutto il codice
– Volumi rappresentativi
• Testare in ambiente di produzione
– Può alterare i dati
– Perturba l’attività degli utenti
• Testare in ambiente di sviluppo
– Va bene al più per test di unità
Installation Worst Practices
• Utilizzare HW inadeguato o sbilanciato
• Installare utilizzando tutti i default
– File di dati sui dischi di sistema!
• Installare componenti non necessarie
• Installare più servizi sulla stessa macchina
I/O Worst Practices
• Scegliere un livello di RAID errato
– RAID 0 non offre protezione!
• Pianificare lo storage pensando allo spazio
• Non allineare le partizioni
• Utilizzare l’unità di allocazione di default (4Kb)
Cosa serve a un database?
Brent Ozar
Administration Worst Practices
Backup and Recovery
• Nessun backup
– In FULL recovery è una bomba in attesa di esplodere
– Ignorare RPO e RTO
• Nessun test di restore
• Nessun controllo di consistenza
– DBCC REPAIR_ALLOW_DATA_LOSS
Il nostro compito è fare il restore, non il backup!
Administration Worst Practices
Security
• Troppi sysadmin
• Utilizzo di SQL Authentication
– Password deboli
• Nessun auditing
Administration Worst Practices
Capacity
• Non controllare lo spazio disco
– Spazio esaurito = database fermo!
– Sto facendo il backup?
• Affidarsi ad autogrow
• Non predimensionare tempdb
– Dimensioni diverse = striping penalty
Administration Worst Practices
Manutenzione
• Non manutenere gli indici e le statistiche
• Creare piani di manutenzione «tuttofare»
• Aggiornare le statistiche dopo aver ricostruito
gli indici
Performance Tuning
Performance Worst Practices
Query Optimization
RBAR: Row By Agonizing Row
– Cursori
– Cicli WHILE
– Cursori lato applicativo
– Funzioni scalari e multi-statement
Jeff Moden
Utilizziamo codice set-based
L’ottimizzatore la sa molto più lunga di noi
Performance Worst Practices
Query Optimization
• Una query per domarli tutti
– L’ottimizzatore è buono, non perfetto
– Molto meglio «divide et impera»
• DISTINCT in tutte le query
• Query HINT
Performance Worst Practices
Indexing
• Accettare tutti i suggerimenti del Tuning Advisor
• Indici duplicati
• Un indice per ogni colonna
– Gli indici non sono gratis!
• Clustered Index non ottimale
– Univoco
– Piccolo
– Immutabile
– Monotòno
Preferire NEWSEQUENTIALID()
A NEWID()
Performance Worst Practices
Server Tuning
• «Lanciare HW» al problema
– Una macchina più veloce non risolve problemi
strutturali
• Usare opzioni «avanzate» senza testare
– NT Fibers (lightweight pooling)
– Priority Boost
Administration Worst Practices
Monitoring
• Gestione reattiva (no monitoring)
• Mancanza di alerting
– Severity > 16
• Troppo rumore negli alert
– Non li guarda più nessuno!
Risorse
Free Tool:
Best Practices Analyzer
• Evidenzia i parametri di configurazione che
non rispettano le best practices
• Evidenzia potenziali problemi
• Offre raccomandazioni
http://www.microsoft.com/en-us/download/details.aspx?id=15289
Risorse
Free e-book:
Troubleshooting
SQL Server
• Jonathan Kehayias
• Ted Krueger
– Gail Shaw
– Paul Randal
http://www.simple-talk.com/books/sql-books/troubleshooting-
sql-server-a-guide-for-the-accidental-dba/
Grazie!
Non dimenticate di compilare
i moduli di feedback.
Commenta la sessione che hai
appena seguito su Twitter
#sqlstart

More Related Content

PPTX
A performance tuning methodology
PPTX
SQL Server Benchmarking, Baselining and Workload Analysis
PPTX
Why do you want to study international management
PDF
Article: ZELA hosts workshop on Corporate Social Responsibility & Business an...
ODP
Londres cris jas
PDF
Joshua Nash 2015 Calendar Project-Burgess Falls State Park- Sparta,TN
PDF
internet security and cyber lawUnit1
PPTX
Big digital oct 2014 ex
A performance tuning methodology
SQL Server Benchmarking, Baselining and Workload Analysis
Why do you want to study international management
Article: ZELA hosts workshop on Corporate Social Responsibility & Business an...
Londres cris jas
Joshua Nash 2015 Calendar Project-Burgess Falls State Park- Sparta,TN
internet security and cyber lawUnit1
Big digital oct 2014 ex

Viewers also liked (11)

PDF
Home technologies
PPTX
Ultimate android app development course
PPTX
Why do you want to study in UWE
PDF
Codflorestal port digital
PPT
PDF
Make an Entrance
PDF
Producao sustentavelpecuarialeiteira
PDF
Țintirea inflației (feb 2012) - Raport trimestrial asupra inflației
PPTX
Big Digital Advisory Services - Customer-Centric Digital Consulting
PDF
อปท (1)
PPT
Int to tourism and hospitality(1)
Home technologies
Ultimate android app development course
Why do you want to study in UWE
Codflorestal port digital
Make an Entrance
Producao sustentavelpecuarialeiteira
Țintirea inflației (feb 2012) - Raport trimestrial asupra inflației
Big Digital Advisory Services - Customer-Centric Digital Consulting
อปท (1)
Int to tourism and hospitality(1)
Ad

Similar to SQL Server Worst Practices (20)

PPTX
Dynamic Schema e Schemaless Tables
PDF
SQL Server Modern Query Processing
PPTX
2014.11.14 Implementare e mantenere un progetto Azure SQL Database
PPTX
No sql introduzione. Corso Sistemi Informativi Politecnico di Milano 12-11-2013
PPTX
2014.11.14 Implementare e mantenere un progetto Azure SQL Database
PPTX
PASS Virtual Chapter - Unit Testing su SQL Server
PDF
RDBMS: pregi e difetti
PPTX
[ITA] Sql Saturday 355 in Parma - New SQL Server databases under source control
PPTX
Implementare e mantenere un progetto azure sql database v.2
PDF
Best Practices on SQL Server
PPTX
Dot netcampus2015 green-template
PPTX
DSTORIE DALLA TRINCEA: TEAM FOUNDATION SERVER IN CASI LIMITE E NON SOLO...
PPTX
Sql start!2019 Migliorare la produttività per lo sviluppo su SQL Server
PDF
Novità di SQL Server 2017
PDF
SQL Server Modern Query Processing
PPTX
TSQL Advanced Query Techniques
PDF
MySQL Tech Tour 2015 - Soluzioni di alta disponibilità con MySQL
PDF
Metadata Driven Pipeline with Microsoft Fabric
PDF
VMUGIT Roma 2016 - vROps Design - Pietro Piutti
PDF
Polyglot Persistance con PostgreSQL, CouchDB, MongoDB, Redis e OrientDB
Dynamic Schema e Schemaless Tables
SQL Server Modern Query Processing
2014.11.14 Implementare e mantenere un progetto Azure SQL Database
No sql introduzione. Corso Sistemi Informativi Politecnico di Milano 12-11-2013
2014.11.14 Implementare e mantenere un progetto Azure SQL Database
PASS Virtual Chapter - Unit Testing su SQL Server
RDBMS: pregi e difetti
[ITA] Sql Saturday 355 in Parma - New SQL Server databases under source control
Implementare e mantenere un progetto azure sql database v.2
Best Practices on SQL Server
Dot netcampus2015 green-template
DSTORIE DALLA TRINCEA: TEAM FOUNDATION SERVER IN CASI LIMITE E NON SOLO...
Sql start!2019 Migliorare la produttività per lo sviluppo su SQL Server
Novità di SQL Server 2017
SQL Server Modern Query Processing
TSQL Advanced Query Techniques
MySQL Tech Tour 2015 - Soluzioni di alta disponibilità con MySQL
Metadata Driven Pipeline with Microsoft Fabric
VMUGIT Roma 2016 - vROps Design - Pietro Piutti
Polyglot Persistance con PostgreSQL, CouchDB, MongoDB, Redis e OrientDB
Ad

More from Gianluca Sartori (7)

PPTX
Benchmarking like a pro
PPTX
Sql server infernals
PPTX
SQL Server 2016 New Security Features
PPTX
Responding to extended events in near real time
PPTX
Sql server security in an insecure world
PPTX
SQL Server Worst Practices - EN
PPTX
My Query is slow, now what?
Benchmarking like a pro
Sql server infernals
SQL Server 2016 New Security Features
Responding to extended events in near real time
Sql server security in an insecure world
SQL Server Worst Practices - EN
My Query is slow, now what?

SQL Server Worst Practices

  • 1. SQL START! ANCONA, 28 SETTEMBRE 2012
  • 2. SQL START! ANCONA, 28 SETTEMBRE 2012 SQL Server Worst Practices Gianluca Sartori gianluca.sartori@sqlconsulting.it
  • 5. Gianluca Sartori • Independent SQL Server consultant • Works with SQL Server since version 7 • MCTS, MCITP, MCT • DBA @ Scuderia Ferrari
  • 6. Agenda • Best practices o Worst practices? • Dove posso sbagliare? – Progettazione – Sviluppo – Installazione – Amministrazione
  • 7. Disclaimer: • Non tutto è bianco o nero • «Dipende» è la risposta migliore Possono esistere casi limite in cui qualcuna di queste worst practice è l’unica soluzione possibile
  • 8. Best Practices vs. Worst Practices • Perché le Best Practices non bastano – Sono troppe – Non c’è tempo – Manca l’esperienza – Non è chiaro cosa succede se non le seguiamo • Perché le Worst Practices servono – Ci mostrano gli errori da non fare – Possiamo imparare dagli errori degli altri
  • 9. Worst Practices Areas Design Development Installation Administration Schema design Naming Data Types Environment HW validation OS configuration SQL installation Recovery Security Capacity Performance Monitoring Code Test
  • 10. Schema Design • Non normalizzare lo schema – 1NF: Una chiave, solo attributi atomici – 2NF: Ogni attributo dipende da tutta la chiave – 3NF: Ogni attributo dipende solo dalla chiave «La chiave, solo la chiave, nient’altro che la chiave, così Codd mi aiuti»
  • 11. Indizi di denormalizzazione • Dati che si ripetono  ridondanze • Dati inconsistenti tra tabelle  anomalie • Dati separati da «,» • ES: john@gmail.com, john@business.com • Dati strutturati in colonne «nota» • Colonne con un suffisso numerico – ES: Zona1, Zona2, Zona3 …
  • 12. Schema Design Worst Practices • Nessuna Primary Key o solo chiavi surrogate – «Id» non è la sola chiave primaria al mondo! • Nessuna Foreign Key – Sono «scomode» • Nessun vincolo CHECK – L’applicazione garantirà la consistenza… • Utilizzo di tipi di dato errati – CAP, Telefono – Date salvate come stringhe • Utilizzo di NULL dove non necessario • Utilizzo di valori «dummy» (es: ‘.’ , 0)
  • 13. Schema Design Worst Practices • Naming conventions inconsistenti – Plurale o singolare? – Italiano / Inglese – Hungarian Notation • tbl… • vw... • Nomi di oggetto o di colonna riservati • Usare il prefisso sp_ – … meno peggio di quanto sembri!
  • 14. Lookup Tables Orders PK order_id int order_date datetime FK2 customer_id int FK1 status_id char(2) FK3 priority_id tinyint Order_Status PK status_id char(2) status_description nvarchar(50) Customers PK customer_id int name varchar(100) address varchar(50) ZIP char(5) city nvarchar(50) FK2 state_id char(2) FK1 country_id char(3) Countries PK country_id char(3) description nvarchar(50) States PK state_id char(2) description nvarchar(50) Order_Priorities PK priority_id tinyint priority_description nvarchar(50) Una tabella di lookup per ogni attributo
  • 15. OTLT: One True Lookup Table Orders PK order_id int order_date datetime FK1 customer_id int status_id char(2) priority_id tinyint Customers PK customer_id int name nvarchar(100) address nvarchar(50) ZIP char(5) city nvarchar(50) state_id char(2) country_id char(3) LookupTable PK table_name sysname PK lookup_code nvarchar(500) lookup_description nvarchar(4000) CREATE TABLE LookupTable ( table_name sysname, lookup_code nvarchar(500), lookup_description nvarchar(4000) ) Una tabella di lookup per tutti gli attributi
  • 16. OTLT: One True Lookup Table • Impossibile usare Foreign Key • Tipi di dati generici  nvarchar(?) – Implicit Conversions • Difficile definire vincoli CHECK • Locking CHECK( CASE WHEN lookup_code = 'states' AND lookup_code LIKE '[A-Z][A-Z]' THEN 1 WHEN lookup_code = 'priorities' AND lookup_code LIKE '[0-9]' THEN 1 WHEN lookup_code = 'countries' AND lookup_code LIKE '[0-9][0-9][0-9]' THEN 1 WHEN lookup_code = 'status' AND lookup_code LIKE '[A-Z][A-Z]' THEN 1 ELSE 0 END = 1 )
  • 17. EAV: Entity, Attribute, Value Customers PK customer_id int name nvarchar(100) address nvarchar(50) ZIP char(5) city nvarchar(50) state_id char(2) country_id char(3) AttributeNames PK attribute_id int PK,FK1 entity_id int attribute_name nvarchar(128) AttributeValues PK,FK1 attribute_id int PK,FK1 entity_id int PK,FK2,FK3 id int value nvarchar(4000) Entities PK entity_id int entity_name nvarchar(128) Orders PK order_id int order_date datetime customer_id int status_id char(2) priority_id tinyint
  • 18. EAV: Entity, Attribute, Value • Svantaggi: – Tipi di dato generici  ES: varchar(4000) – No Foreign Key – No CHECK constraints – Accessi multipli alla stessa tabella • Una lettura per ogni attributo • Vantaggi – Schema dinamico: non richiede modifiche al DB • Replica, ambienti distribuiti
  • 19. EAV: Entity, Attribute, Value • Workaround: – PIVOT / Crosstab – Viste + INSTEAD OF triggers • Alternative: – SPARSE columns – XML – Key-value store databases • Azure Table storage, Redis – Document-oriented databases • MongoDB, RavenDB
  • 21. Development Worst Practices Development Environment • Non versionare lo schema del DB • Non fornire un livello di astrazione – Viste, Functions, Stored Procedures • Sviluppare con privilegi di sysadmin – In produzione non ci saranno!
  • 22. Development Worst Practices Code • Nessuna transazione • Nessuna gestione degli errori – @@ERROR appartiene al passato! • Utilizzo di livelli di isolamento errati – NOLOCK = nessuna consistenza! • SELECT * • SQL dinamico con valori hardcoded • Codice suscettibile alla SQL injection
  • 23. Development Worst Practices Test • Non testare tutto il codice – Volumi rappresentativi • Testare in ambiente di produzione – Può alterare i dati – Perturba l’attività degli utenti • Testare in ambiente di sviluppo – Va bene al più per test di unità
  • 24. Installation Worst Practices • Utilizzare HW inadeguato o sbilanciato • Installare utilizzando tutti i default – File di dati sui dischi di sistema! • Installare componenti non necessarie • Installare più servizi sulla stessa macchina
  • 25. I/O Worst Practices • Scegliere un livello di RAID errato – RAID 0 non offre protezione! • Pianificare lo storage pensando allo spazio • Non allineare le partizioni • Utilizzare l’unità di allocazione di default (4Kb)
  • 26. Cosa serve a un database? Brent Ozar
  • 27. Administration Worst Practices Backup and Recovery • Nessun backup – In FULL recovery è una bomba in attesa di esplodere – Ignorare RPO e RTO • Nessun test di restore • Nessun controllo di consistenza – DBCC REPAIR_ALLOW_DATA_LOSS Il nostro compito è fare il restore, non il backup!
  • 28. Administration Worst Practices Security • Troppi sysadmin • Utilizzo di SQL Authentication – Password deboli • Nessun auditing
  • 29. Administration Worst Practices Capacity • Non controllare lo spazio disco – Spazio esaurito = database fermo! – Sto facendo il backup? • Affidarsi ad autogrow • Non predimensionare tempdb – Dimensioni diverse = striping penalty
  • 30. Administration Worst Practices Manutenzione • Non manutenere gli indici e le statistiche • Creare piani di manutenzione «tuttofare» • Aggiornare le statistiche dopo aver ricostruito gli indici
  • 32. Performance Worst Practices Query Optimization RBAR: Row By Agonizing Row – Cursori – Cicli WHILE – Cursori lato applicativo – Funzioni scalari e multi-statement Jeff Moden Utilizziamo codice set-based L’ottimizzatore la sa molto più lunga di noi
  • 33. Performance Worst Practices Query Optimization • Una query per domarli tutti – L’ottimizzatore è buono, non perfetto – Molto meglio «divide et impera» • DISTINCT in tutte le query • Query HINT
  • 34. Performance Worst Practices Indexing • Accettare tutti i suggerimenti del Tuning Advisor • Indici duplicati • Un indice per ogni colonna – Gli indici non sono gratis! • Clustered Index non ottimale – Univoco – Piccolo – Immutabile – Monotòno Preferire NEWSEQUENTIALID() A NEWID()
  • 35. Performance Worst Practices Server Tuning • «Lanciare HW» al problema – Una macchina più veloce non risolve problemi strutturali • Usare opzioni «avanzate» senza testare – NT Fibers (lightweight pooling) – Priority Boost
  • 36. Administration Worst Practices Monitoring • Gestione reattiva (no monitoring) • Mancanza di alerting – Severity > 16 • Troppo rumore negli alert – Non li guarda più nessuno!
  • 37. Risorse Free Tool: Best Practices Analyzer • Evidenzia i parametri di configurazione che non rispettano le best practices • Evidenzia potenziali problemi • Offre raccomandazioni http://www.microsoft.com/en-us/download/details.aspx?id=15289
  • 38. Risorse Free e-book: Troubleshooting SQL Server • Jonathan Kehayias • Ted Krueger – Gail Shaw – Paul Randal http://www.simple-talk.com/books/sql-books/troubleshooting- sql-server-a-guide-for-the-accidental-dba/
  • 39. Grazie! Non dimenticate di compilare i moduli di feedback. Commenta la sessione che hai appena seguito su Twitter #sqlstart

Editor's Notes

  • #8: Lo scopo non è criticare, ma far capire errori che io per primo ho fatto nella mia carriera
  • #14: Agganciare la worst practice trascurabile sp_ con Worst Practice tremenda OTLT!!