Todos los que trabajamos con bases de datos relacionales hemos aprendido (o estamos aprendiendo) que SQL es diferente. Obtener los resultados deseados, y hacerlo de manera eficiente, implica un proceso tedioso que se caracteriza en parte por aprender paradigmas desconocidos y descubrir que algunos de nuestros patrones de programación más familiares no funcionan aquí. ¿Cuáles son los antipatrones comunes que has visto (o que has cometido)?
sql
anti-patterns
le dorfier
fuente
fuente
Respuestas:
Me decepciona constantemente la tendencia de la mayoría de los programadores a mezclar su lógica de interfaz de usuario en la capa de acceso a datos:
Normalmente, los programadores hacen esto porque tienen la intención de vincular su conjunto de datos directamente a una cuadrícula, y es conveniente tener el formato del servidor SQL en el lado del servidor que el formato en el cliente.
Las consultas como la que se muestra arriba son extremadamente frágiles porque acoplan estrechamente la capa de datos a la capa de la interfaz de usuario. Además de eso, este estilo de programación evita a fondo que los procedimientos almacenados sean reutilizables.
fuente
Aquí están mis 3 mejores.
Número 1. Error al especificar una lista de campos. (Editar: para evitar confusiones: esta es una regla de código de producción. No se aplica a los scripts de análisis únicos, a menos que yo sea el autor).
debiera ser
Número 2. Usando un cursor y un bucle while, cuando lo hará un bucle while con una variable de bucle.
Número 3. DateLogic a través de tipos de cadena.
Debiera ser
He visto un pico reciente de "Una consulta es mejor que dos, ¿verdad?"
Esta consulta requiere dos o tres planes de ejecución diferentes según los valores de los parámetros. Solo se genera un plan de ejecución y se atasca en la memoria caché para este texto sql. Ese plan se utilizará independientemente del valor de los parámetros. Esto da como resultado un bajo rendimiento intermitente. Es mucho mejor escribir dos consultas (una consulta por plan de ejecución previsto).
fuente
Campos de contraseña legibles por humanos , egad. Autoexplicativo.
Utilizando LIKE contra columnas indexadas , estoy casi tentado a decir LIKE en general.
Reciclaje de valores PK generados por SQL.
Sorpresa, nadie mencionó la mesa de Dios todavía. Nada dice "orgánico" como 100 columnas de banderas de bits, cadenas grandes y enteros.
Luego está el patrón "Echo de menos los archivos .ini" : almacenar CSV, cadenas delimitadas por tuberías u otros datos requeridos para analizar en campos de texto grandes.
Y para el servidor MS SQL, el uso de cursores en absoluto . Hay una mejor manera de hacer cualquier tarea de cursor.
Editado porque hay tantos!
fuente
LIKE '%LIKE'
.No tiene que profundizar en ello: no usar declaraciones preparadas.
fuente
Usando alias de tabla sin sentido:
Hace que leer una declaración SQL grande sea mucho más difícil de lo necesario
fuente
fuente
Mis errores son las tablas de acceso de 450 columnas que ha preparado el hijo de 8 años de los mejores amigos del Director Gerente y la tabla de búsqueda dudosa que solo existe porque alguien no sabe cómo normalizar una estructura de datos correctamente.
Por lo general, esta tabla de búsqueda se ve así:
He perdido la cuenta de la cantidad de clientes que he visto que tienen sistemas que dependen de abominaciones como esta.
fuente
Los que más me disgustan son
Uso de espacios al crear tablas, sprocs, etc. Estoy bien con CamelCase o under_scores y singular o plural y MAYÚSCULAS o minúsculas, pero tengo que referirme a una tabla o columna [con espacios], especialmente si [está espaciado de manera extraña] (sí, Me he encontrado con esto) realmente me irrita.
Datos desnormalizados. Una tabla no tiene que estar perfectamente normalizada, pero cuando me encuentro con una tabla de empleados que tiene información sobre su puntaje de evaluación actual o su principal, me dice que probablemente necesite hacer una tabla separada en algún momento y luego trate de mantenerlos sincronizados. Normalizaré los datos primero y luego, si veo un lugar donde la desnormalización ayuda, lo consideraré.
Uso excesivo de vistas o cursores. Las vistas tienen un propósito, pero cuando cada tabla está envuelta en una vista, es demasiado. He tenido que usar cursores varias veces, pero generalmente puedes usar otros mecanismos para esto.
Acceso. ¿Puede un programa ser un antipatrón? Tenemos SQL Server en mi trabajo, pero varias personas usan el acceso debido a su disponibilidad, "facilidad de uso" y "amabilidad" para usuarios no técnicos. Aquí hay demasiado para entrar, pero si has estado en un entorno similar, ya sabes.
fuente
use SP como prefijo del nombre del procedimiento de tienda porque primero buscará en la ubicación de procedimientos del sistema en lugar de los personalizados.
fuente
Uso excesivo de tablas y cursores temporales.
fuente
Para almacenar valores de tiempo, solo se debe usar la zona horaria UTC. La hora local no debe ser utilizada.
fuente
usando @@ IDENTITY en lugar de SCOPE_IDENTITY ()
Citado de esta respuesta :
fuente
Reutilizar un campo 'muerto' para algo para lo que no estaba destinado (por ejemplo, almacenar datos de usuario en un campo 'Fax'), ¡aunque es muy tentador como una solución rápida!
fuente
y suponiendo que el resultado se ordenará por some_column. He visto esto un poco con Sybase donde se cumple el supuesto (por ahora).
fuente
O bien, agrupando todo en una sola línea.
fuente
La
FROM TableA, TableB WHERE
sintaxis de JOINS en lugar deFROM TableA INNER JOIN TableB ON
Suponiendo que una consulta se devolverá ordenada de cierta manera sin poner una cláusula ORDER BY, solo porque esa fue la forma en que se mostró durante la prueba en la herramienta de consulta.
fuente
Aprender SQL en los primeros seis meses de su carrera y nunca aprender nada más durante los próximos 10 años. En particular, no aprender o usar eficazmente las funciones de SQL analítico / ventanas. En particular, el uso de over () y la partición por.
Consulte el Apéndice A del O'Reilly SQL Cookbook para obtener una buena descripción de las funciones de ventanas.
fuente
Necesito poner mi propio favorito actual aquí, solo para completar la lista. Mi antipatrón favorito no prueba tus consultas .
Esto aplica cuando:
Y cualquier prueba realizada contra datos atípicos o insuficientes no cuenta. Si se trata de un procedimiento almacenado, coloque la declaración de prueba en un comentario y guárdela con los resultados. De lo contrario, póngalo en un comentario en el código con los resultados.
fuente
Abuso de mesa temporal.
Específicamente este tipo de cosas:
No cree una tabla temporal a partir de una consulta, solo para eliminar las filas que no necesita.
Y sí, he visto páginas de código de esta forma en bases de datos de producción.
fuente
Visión contraria: obsesión excesiva con la normalización.
La mayoría de los sistemas SQL / RBDB ofrecen muchas características (transacciones, replicación) que son bastante útiles, incluso con datos no normalizados. El espacio en disco es barato y, a veces, puede ser más simple (código más fácil, tiempo de desarrollo más rápido) manipular / filtrar / buscar datos recuperados, que escribir un esquema 1NF y lidiar con todas las molestias (uniones complejas, subselecciones desagradables) , etc.)
He descubierto que los sistemas sobre normalizados suelen ser una optimización prematura, especialmente durante las primeras etapas de desarrollo.
(más pensamientos sobre él ... http://writeonly.wordpress.com/2008/12/05/simple-object-db-using-json-and-python-sqlite/ )
fuente
Acabo de armar este, basado en algunas de las respuestas SQL aquí en SO.
Es un antipatrón serio pensar que los desencadenantes son a las bases de datos como lo son los controladores de eventos a OOP. Existe la percepción de que cualquier lógica antigua se puede poner en disparadores, para que se active cuando una transacción (evento) ocurre en una mesa.
No es verdad. Una de las grandes diferencias es que los disparadores son síncronos, con una venganza, porque son síncronos en una operación de configuración, no en una operación de fila. En el lado OOP, exactamente lo contrario: los eventos son una forma eficiente de implementar transacciones asincrónicas.
fuente
Procedimientos almacenados o funciones sin ningún comentario ...
fuente
1) No sé si es un antipatrón "oficial", pero no me gusta e intento evitar los literales de cadena como valores mágicos en una columna de base de datos.
Un ejemplo de la tabla 'imagen' de MediaWiki:
(Acabo de notar una carcasa diferente, otra cosa para evitar)
Diseño casos como búsquedas int en tablas ImageMediaType e ImageMajorMime con claves primarias int.
2) conversión de fecha / cadena que se basa en configuraciones específicas de NLS
sin identificador de formato
fuente
Subconsultas idénticas en una consulta.
fuente
La vista alterada: una vista que se modifica con demasiada frecuencia y sin previo aviso ni razón. El cambio se notará en el momento más inapropiado o, peor aún, se equivocará y nunca se notará. Tal vez su aplicación se interrumpirá porque alguien pensó en un mejor nombre para esa columna. Como norma, las vistas deberían ampliar la utilidad de las tablas base mientras se mantiene un contrato con los consumidores. Solucione problemas pero no agregue características o peor cambie el comportamiento, para eso cree una nueva vista. Para mitigar, no comparta vistas con otros proyectos y use CTE cuando las plataformas lo permitan. Si su tienda tiene un DBA, probablemente no pueda cambiar las vistas, pero todas sus vistas estarán desactualizadas o serán inútiles en ese caso.
The! Paramed: ¿Puede una consulta tener más de un propósito? Probablemente, pero la próxima persona que lo lea no lo sabrá hasta la meditación profunda. Incluso si no los necesita en este momento, es probable que lo haga, incluso si es "solo" para depurar. Agregar parámetros reduce el tiempo de mantenimiento y mantiene las cosas SECAS. Si tiene una cláusula where, debe tener parámetros.
El caso para no CASE -
fuente
Los dos que más encuentro y que pueden tener un costo significativo en términos de rendimiento son:
Usar cursores en lugar de una expresión basada en conjuntos. Supongo que esto ocurre con frecuencia cuando el programador está pensando con procedimientos.
Usando subconsultas correlacionadas, cuando una unión a una tabla derivada puede hacer el trabajo.
fuente
Poner cosas en tablas temporales, especialmente las personas que cambian de SQL Server a Oracle tienen la costumbre de usar en exceso las tablas temporales. Solo usa sentencias select anidadas.
fuente
Desarrolladores que escriben consultas sin tener una buena idea sobre qué hace que las aplicaciones SQL (tanto consultas individuales como sistemas multiusuario) sean rápidas o lentas. Esto incluye ignorancia sobre:
fuente
Usar SQL como un paquete ISAM (Método de acceso secuencial indexado) glorificado. En particular, anidar cursores en lugar de combinar declaraciones SQL en una sola declaración, aunque más grande. Esto también cuenta como 'abuso del optimizador' ya que de hecho no hay mucho que pueda hacer el optimizador. Esto se puede combinar con declaraciones no preparadas para la máxima ineficiencia:
La solución correcta (casi siempre) es combinar las dos instrucciones SELECT en una:
La única ventaja de la versión de doble bucle es que puede detectar fácilmente los saltos entre los valores en la Tabla 1 porque el bucle interno termina. Esto puede ser un factor en los informes de interrupción de control.
Además, la clasificación en la aplicación suele ser un no-no.
fuente
Usando claves primarias como un sustituto para direcciones de registro y usando claves externas como un sustituto para punteros incrustados en registros.
fuente