online - database design software
Errores de desarrollo de base de datos cometidos por desarrolladores de aplicaciones (30)
- No usar el control de versiones en el esquema de base de datos
- Trabajando directamente contra una base de datos en vivo
- No leer y comprender conceptos de bases de datos más avanzados (índices, índices agrupados, restricciones, vistas materializadas, etc.)
- Si no se prueba la escalabilidad ... los datos de prueba de solo 3 o 4 filas nunca le darán una imagen real del rendimiento en vivo real
¿Cuáles son los errores comunes de desarrollo de bases de datos cometidos por los desarrolladores de aplicaciones?
- Usando un ORM para hacer actualizaciones masivas
- Seleccionando más datos de los necesarios. Una vez más, normalmente se hace cuando se utiliza un ORM
- Disparar sqls en un bucle.
- No tener buenos datos de prueba y notar la degradación del rendimiento solo en datos en vivo.
Pensando que son DBA y modeladores / diseñadores de datos cuando no tienen adoctrinamiento formal de ningún tipo en esas áreas.
Pensar que su proyecto no requiere un DBA porque todo eso es fácil / trivial.
No discernir correctamente entre el trabajo que se debe hacer en la base de datos y el trabajo que se debe hacer en la aplicación.
No validar copias de seguridad, o no hacer copias de seguridad.
Incrustación de SQL en bruto en su código.
¿El problema número uno? Sólo prueban en bases de datos de juguetes. Así que no tienen idea de que su SQL se arrastrará cuando la base de datos crezca, y alguien tiene que venir y arreglarlo más tarde (ese sonido que se puede escuchar es el de mis dientes).
En mi experiencia:
No se comunica con DBA con experiencia.
Me gustaría agregar: Favorecer el código "Elegante" sobre el código de alto rendimiento. El código que funciona mejor contra las bases de datos suele ser desagradable para el desarrollador de la aplicación.
Creyendo esa tontería acerca de la optimización prematura. Las bases de datos deben considerar el rendimiento en el diseño original y en cualquier desarrollo posterior. El rendimiento es el 50% del diseño de la base de datos (40% es integridad de los datos y el último 10% es seguridad), en mi opinión. Las bases de datos que no se crean de abajo hacia arriba tendrán un mal desempeño una vez que los usuarios reales y el tráfico real se coloquen en la base de datos. ¡La optimización prematura no significa ninguna optimización! No significa que deba escribir código que casi siempre tendrá un mal rendimiento porque le resulta más fácil (cursores, por ejemplo, que nunca deberían permitirse en una base de datos de producción a menos que todo lo demás haya fallado). Esto significa que no es necesario mirar a exprimir ese último poco de rendimiento hasta que lo necesite. Se sabe mucho sobre lo que funcionará mejor en las bases de datos, por lo que ignorar esto en el diseño y el desarrollo es, en el mejor de los casos, miope.
No utilizar índices.
No utilizar consultas parametrizadas.Son bastante útiles para detener la inyección SQL .
Este es un ejemplo específico de no sanear los datos de entrada, mencionado en otra respuesta.
Olvidando establecer relaciones entre las tablas. Recuerdo que tuve que limpiar esto cuando comencé a trabajar con mi empleador actual.
Usando Access en lugar de una base de datos "real". Hay un montón de grandes bases de datos pequeñas e incluso gratuitas como SQL Express , MySQL y SQLite que funcionarán y escalarán mucho mejor. Las aplicaciones a menudo necesitan escalar de maneras inesperadas.
Usando Excel para almacenar (enormes cantidades de) datos.
He visto compañías sosteniendo miles de filas y utilizando varias hojas de trabajo (debido al límite de fila de 65535 en versiones anteriores de Excel).
Excel es adecuado para informes, presentación de datos y otras tareas, pero no debe tratarse como una base de datos.
Uso excesivo y / o dependencia de procedimientos almacenados.
Algunos desarrolladores de aplicaciones ven los procedimientos almacenados como una extensión directa del código de nivel medio / front-end. Esto parece ser un rasgo común en los desarrolladores de pila de Microsoft (yo soy uno, pero he crecido fuera de él) y produce muchos procedimientos almacenados que realizan una lógica de negocios compleja y procesamiento de flujo de trabajo. Esto se hace mucho mejor en otros lugares.
Los procedimientos almacenados son útiles cuando se ha comprobado realmente que algún factor técnico real requiere su uso (por ejemplo, rendimiento y seguridad) Por ejemplo, mantener la agregación / filtrado de grandes conjuntos de datos "cerca de los datos".
Hace poco tuve que ayudar a mantener y mejorar una gran aplicación de escritorio de Delphi, de la cual el 70% de la lógica de negocios y las reglas se implementaron en 1400 procedimientos almacenados de SQL Server (el resto en controladores de eventos de IU). Esto fue una pesadilla, principalmente debido a la dificultad de introducir pruebas unitarias efectivas a TSQL, falta de encapsulación y herramientas deficientes (depuradores, editores).
Trabajando con un equipo de Java en el pasado, rápidamente descubrí que a menudo ocurre todo lo contrario en ese entorno. Un arquitecto de Java me dijo una vez: "La base de datos es para datos, no para código".
En estos días, creo que es un error no considerar los procedimientos almacenados en absoluto, pero se deben usar con moderación (no por defecto) en situaciones en las que proporcionan beneficios útiles (consulte las otras respuestas).
¡No ejecutar una consulta SELECT correspondiente antes de ejecutar la consulta DELETE (particularmente en bases de datos de producción)!
1. No utilizar índices adecuados.
Esto es relativamente fácil pero todavía sucede todo el tiempo. Las claves externas deben tener índices en ellas. Si está utilizando un campo en un WHERE
debería (probablemente) tener un índice en él. Dichos índices a menudo deben cubrir varias columnas basadas en las consultas que necesita ejecutar.
2. No hacer cumplir la integridad referencial.
Su base de datos puede variar aquí, pero si su base de datos es compatible con integridad referencial, lo que significa que todas las claves foráneas tienen la garantía de apuntar a una entidad existente, debe usarla.
Es bastante común ver este fallo en las bases de datos MySQL. No creo que MyISAM lo apoye. InnoDB lo hace. Encontrará personas que están usando MyISAM o aquellas que están usando InnoDB pero que no lo están usando de todos modos.
Más aquí:
- ¿Qué tan importantes son las restricciones como NOT NULL y FOREIGN KEY si siempre controlaré la entrada de mi base de datos con php?
- ¿Son realmente necesarias las claves externas en el diseño de una base de datos?
- ¿Son realmente necesarias las claves externas en el diseño de una base de datos?
3. Usar claves primarias naturales (en lugar de sustitutas) (técnicas)
Las claves naturales son claves basadas en datos significativos externos que son (aparentemente) únicos. Los ejemplos comunes son códigos de productos, códigos estatales de dos letras (EE. UU.), Números de seguridad social, etc. Las claves primarias sustitutas o técnicas son aquellas que no tienen ningún significado fuera del sistema. Se han inventado exclusivamente para identificar la entidad y suelen ser campos que se incrementan automáticamente (SQL Server, MySQL, otros) o secuencias (especialmente Oracle).
En mi opinión siempre debes usar claves sustitutas. Este problema ha surgido en estas preguntas:
- ¿Cómo te gustan tus llaves primarias?
- ¿Cuál es la mejor práctica para las claves primarias en las tablas?
- ¿Qué formato de clave principal usaría en esta situación?
- Surrogate vs. natural / business keys
- ¿Debo tener un campo de clave principal dedicado?
Este es un tema un tanto controvertido sobre el cual no obtendrás un acuerdo universal. Si bien puede encontrar algunas personas que piensan que las claves naturales están bien en algunas situaciones, no encontrará ninguna crítica a las claves sustitutas que no sea discutiblemente innecesaria. Eso es un pequeño inconveniente si me preguntas.
Recuerde, incluso los países pueden dejar de existir (por ejemplo, Yugoslavia).
4. Escribiendo consultas que requieren DISTINCT
para trabajar
A menudo se ve esto en las consultas generadas por ORM. Mire la salida del registro de Hibernate y verá que todas las consultas comienzan con:
SELECT DISTINCT ...
Este es un atajo para asegurarse de que no devuelva filas duplicadas y, por lo tanto, obtenga objetos duplicados. A veces también verás gente haciendo esto. Si lo ves demasiado es una verdadera bandera roja. No es que DISTINCT
sea malo o no tenga aplicaciones válidas. Lo hace (en ambos casos) pero no es un sustituto o un recurso para escribir consultas correctas.
De por qué odio DISTINTAR :
Donde las cosas empiezan a ponerse mal, en mi opinión es cuando un desarrollador está creando una consulta sustancial, uniendo tablas, y de repente se da cuenta de que parece que está obteniendo filas duplicadas (o incluso más) y su respuesta inmediata ... su "solución" a este "problema" es lanzar la palabra clave DISTINCT y POOF todos sus problemas desaparecen.
5. Favorecer la agregación sobre las uniones.
Otro error común por parte de los desarrolladores de aplicaciones de bases de datos es no darse cuenta de que la agregación mucho más costosa (es decir, la cláusula GROUP BY
) se puede comparar con las uniones.
Para darle una idea de lo generalizado que es esto, he escrito sobre este tema varias veces aquí y me han votado mucho por ello. Por ejemplo:
De la declaración SQL - "unirse" vs "agrupar por y teniendo" :
Primera consulta:
SELECT userid FROM userrole WHERE roleid IN (1, 2, 3) GROUP by userid HAVING COUNT(1) = 3
Tiempo de consulta: 0,312 s
Segunda consulta:
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
Tiempo de consulta: 0.016 s
Está bien. La versión de unión que propuse es veinte veces más rápida que la versión agregada.
6. No simplificar consultas complejas a través de vistas.
No todos los proveedores de bases de datos admiten vistas, pero para aquellos que lo hacen, pueden simplificar enormemente las consultas si se utilizan con criterio. Por ejemplo, en un proyecto usé un modelo genérico de Party para CRM. Esta es una técnica de modelado extremadamente potente y flexible, pero puede llevar a muchas uniones. En este modelo había:
- Partido : personas y organizaciones;
- Rol del partido : cosas que hicieron esos partidos, por ejemplo Empleado y Empleador;
- Relación de rol de partido : cómo esos roles se relacionan entre sí.
Ejemplo:
- Ted es una Persona, siendo un subtipo de Partido;
- Ted tiene muchos roles, uno de los cuales es Empleado;
- Intel es una organización, siendo un subtipo de un partido;
- Intel tiene muchos roles, uno de los cuales es el empleador;
- Intel emplea a Ted, lo que significa que existe una relación entre sus respectivos roles.
Así que hay cinco mesas unidas para vincular a Ted con su empleador. Usted asume que todos los empleados son Personas (no organizaciones) y proporciona esta vista de ayuda:
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
Y, de repente, tiene una vista muy simple de los datos que desea pero en un modelo de datos altamente flexible.
7. No desinfectar la entrada.
Esta es una enorme Ahora me gusta PHP pero si no sabes lo que estás haciendo, es muy fácil crear sitios vulnerables a ataques. Nada lo resume mejor que la historia de las pequeñas mesas de Bobby .
Los datos proporcionados por el usuario a través de URL, datos de formulario y cookies siempre deben tratarse como hostiles y desinfectados. Asegúrese de obtener lo que espera.
8. No usar declaraciones preparadas.
Las declaraciones preparadas son cuando compila una consulta menos los datos utilizados en inserciones, actualizaciones y cláusulas WHERE
y luego la proporciona. Por ejemplo:
SELECT * FROM users WHERE username = ''bob''
vs
SELECT * FROM users WHERE username = ?
o
SELECT * FROM users WHERE username = :username
Dependiendo de su plataforma.
He visto bases de datos que se han puesto de rodillas al hacer esto. Básicamente, cada vez que una base de datos moderna encuentra una nueva consulta, debe compilarla. Si encuentra una consulta que se ha visto antes, le está dando a la base de datos la oportunidad de almacenar en caché la consulta compilada y el plan de ejecución. Al hacer mucho la consulta, le está dando a la base de datos la oportunidad de averiguarlo y optimizarlo (por ejemplo, fijando la consulta compilada en la memoria).
El uso de declaraciones preparadas también le proporcionará estadísticas significativas sobre la frecuencia con la que se utilizan ciertas consultas.
Las declaraciones preparadas también lo protegerán mejor contra ataques de inyección de SQL.
9. No se normaliza lo suficiente
La normalización de la base de datos es básicamente el proceso de optimizar el diseño de la base de datos o cómo organizar sus datos en tablas.
Esta misma semana, encontré un código donde alguien había implosionado una matriz y la había insertado en un solo campo en una base de datos. Normalizar eso sería tratar el elemento de esa matriz como una fila separada en una tabla secundaria (es decir, una relación de uno a varios).
Esto también surgió en el método Best para almacenar una lista de ID de usuario :
He visto en otros sistemas que la lista se almacena en una matriz de PHP serializada.
Pero la falta de normalización viene en muchas formas.
Más:
- Normalización: ¿Hasta dónde es suficiente?
- SQL por diseño: por qué necesita la normalización de la base de datos
10. Normalizar demasiado
Esto puede parecer una contradicción con el punto anterior, pero la normalización, como muchas otras cosas, es una herramienta. Es un medio para un fin y no un fin en sí mismo. Creo que muchos desarrolladores olvidan esto y comienzan a tratar un "medio" como un "fin". La prueba de unidad es un buen ejemplo de esto.
Una vez trabajé en un sistema que tenía una gran jerarquía para los clientes que eran algo así como:
Licensee -> Dealer Group -> Company -> Practice -> ...
de modo que tuvo que unir aproximadamente 11 tablas antes de poder obtener datos significativos. Fue un buen ejemplo de la normalización llevada demasiado lejos.
Más concretamente, la desnormalización cuidadosa y considerada puede tener enormes beneficios de rendimiento, pero hay que tener mucho cuidado al hacer esto.
Más:
- ¿Por qué demasiada normalización de la base de datos puede ser una cosa mala?
- ¿Hasta dónde llevar la normalización en el diseño de bases de datos?
- Cuándo no normalizar su base de datos SQL
- Tal vez la normalización no sea normal
- La madre de todos los debates de normalización de bases de datos sobre la codificación del horror
11. Usando arcos exclusivos.
Un arco exclusivo es un error común cuando se crea una tabla con dos o más claves externas donde una y solo una de ellas puede ser no nula. Gran error. Por un lado, es mucho más difícil mantener la integridad de los datos. Después de todo, incluso con integridad referencial, nada impide que se configuren dos o más de estas claves externas (a pesar de las restricciones de verificación complejas).
De una guía práctica para el diseño de bases de datos relacionales :
Hemos aconsejado encarecidamente que no se construya un arco exclusivo siempre que sea posible, por la buena razón de que pueden ser incómodos para escribir código y plantear más dificultades de mantenimiento.
12. No hacer análisis de rendimiento en las consultas en absoluto
El pragmatismo reina supremo, particularmente en el mundo de la base de datos. Si se atiene a los principios hasta el punto de que se han convertido en un dogma, es muy probable que haya cometido errores. Tomemos el ejemplo de las consultas agregadas de arriba. La versión agregada puede parecer "agradable" pero su rendimiento es lamentable. Una comparación de desempeño debería haber terminado el debate (pero no fue así) pero más al punto: en primer lugar es ignorante, incluso peligroso, emitir tales puntos de vista mal informados.
13. Exceso de confianza en UNION ALL y particularmente UNION constructos
Una UNION en términos SQL simplemente concatena conjuntos de datos congruentes, lo que significa que tienen el mismo tipo y número de columnas. La diferencia entre ellos es que UNION ALL es una concatenación simple y debe preferirse siempre que sea posible, mientras que UNION hará implícitamente un DISTINTO para eliminar las tuplas duplicadas.
Las UNIONES, como DISTINCT, tienen su lugar. Hay aplicaciones válidas. Pero si te encuentras haciendo muchas de ellas, especialmente en subconsultas, entonces probablemente estás haciendo algo mal. Ese podría ser el caso de una construcción de consultas deficiente o un modelo de datos mal diseñado que lo obligue a hacer tales cosas.
Las UNIONES, particularmente cuando se usan en combinaciones o subconsultas dependientes, pueden paralizar una base de datos. Intenta evitarlos siempre que sea posible.
14. Uso de condiciones OR en consultas
Esto puede parecer inofensivo. Después de todo, los AND están bien. O debería estar bien también, ¿verdad? Incorrecto. Básicamente, una condición AND restringe el conjunto de datos mientras que una condición OR lo aumenta pero no de una manera que se preste a la optimización. Particularmente cuando las diferentes condiciones de OR pueden intersecar, forzando así al optimizador a realizar una operación DISTINTA en el resultado.
Malo:
... WHERE a = 2 OR a = 5 OR a = 11
Mejor:
... WHERE a IN (2, 5, 11)
Ahora su optimizador de SQL puede convertir efectivamente la primera consulta en la segunda. Pero puede que no. Simplemente no lo hagas.
15. No diseñar su modelo de datos para prestarse a soluciones de alto rendimiento.
Este es un punto difícil de cuantificar. Se observa típicamente por su efecto. Si se encuentra escribiendo consultas genéricas para tareas relativamente simples o si las consultas para encontrar información relativamente sencilla no son eficientes, entonces probablemente tenga un modelo de datos deficiente.
De alguna manera, este punto resume todos los anteriores, pero es más bien una advertencia de que hacer cosas como la optimización de consultas a menudo se hace primero cuando se debe hacer segundo. En primer lugar, debe asegurarse de tener un buen modelo de datos antes de intentar optimizar el rendimiento. Como dijo Knuth:
La optimización temprana es la raíz de todo mal
16. Uso incorrecto de transacciones de base de datos
Todos los cambios de datos para un proceso específico deben ser atómicos. Es decir, si la operación tiene éxito, lo hace completamente. Si falla, los datos se mantienen sin cambios. - No debería haber ninguna posibilidad de cambios a medio hacer.
Idealmente, la forma más sencilla de lograr esto es que todo el diseño del sistema debe esforzarse por admitir todos los cambios de datos a través de sentencias individuales INSERT / UPDATE / DELETE. En este caso, no se necesita un manejo especial de transacciones, ya que su motor de base de datos debería hacerlo automáticamente.
Sin embargo, si algún proceso requiere que se realicen varias declaraciones como una unidad para mantener los datos en un estado coherente, entonces es necesario un control de transacción adecuado.
- Comience una transacción antes de la primera declaración.
- Confirmar la transacción después de la última declaración.
- En cualquier error, deshacer la transacción. Y muy NB! No olvide omitir / abortar todas las declaraciones que siguen después del error.
También se recomienda prestar especial atención a las subacciones de cómo interactúan la capa de conectividad de la base de datos y el motor de la base de datos a este respecto.
17. No entender el paradigma ''basado en conjuntos''.
El lenguaje SQL sigue un paradigma específico adecuado para tipos específicos de problemas. A pesar de las diversas extensiones específicas del proveedor, el lenguaje tiene dificultades para resolver problemas que son triviales en lenguajes como Java, C #, Delphi, etc.
Esta falta de comprensión se manifiesta de varias maneras.
- Imponer inadecuadamente demasiada lógica procesal o imperativa en la base de datos.
- Uso inadecuado o excesivo de los cursores. Especialmente cuando una sola consulta sería suficiente.
- Suponiendo incorrectamente que los disparos se activan una vez por fila afectados en las actualizaciones de varias filas.
Determine una clara división de responsabilidades y procure utilizar la herramienta adecuada para resolver cada problema.
1: uso innecesario de una función en un valor en una cláusula where con el resultado de que no se usa ese índice.
Ejemplo:
where to_char(someDate,''YYYYMMDD'') between :fromDate and :toDate
en lugar de
where someDate >= to_date(:fromDate,''YYYYMMDD'') and someDate < to_date(:toDate,''YYYYMMDD'')+1
Y, en menor medida, no agregar índices funcionales a los valores que los necesitan ...
2 - No agregar restricciones de verificación para asegurar la validez de los datos. Las restricciones pueden ser utilizadas por el optimizador de consultas, y REALMENTE ayudan a garantizar que pueda confiar en sus invariantes. Simplemente no hay razón para no usarlos.
3 - Agregar columnas no normalizadas a las tablas por pura pereza o presión de tiempo. Las cosas usualmente no están diseñadas de esta manera, pero evolucionan en esto. El resultado final, sin fallar, es un montón de trabajo tratando de limpiar el desastre cuando te muerde la integridad de los datos perdidos en futuras evoluciones.
Piense en esto, una tabla sin datos es muy barata de rediseñar. Una tabla con un par de millones de registros sin integridad ... no es tan barato de rediseñar. Por lo tanto, hacer el diseño correcto al crear la columna o tabla se amortiza a intervalos.
4 - no tanto acerca de la base de datos en sí, sino de hecho molesto. No importa la calidad del código de SQL. El hecho de que su SQL se exprese en texto no permite esconder la lógica en montones de algoritmos de manipulación de cadenas. Es perfectamente posible escribir SQL en texto de una manera que sea realmente legible por su compañero programador.
Bajo rendimiento causado por subconsultas correlacionadas
La mayoría de las veces desea evitar subconsultas correlacionadas. Una subconsulta se correlaciona si, dentro de la subconsulta, hay una referencia a una columna de la consulta externa. Cuando esto sucede, la subconsulta se ejecuta al menos una vez por cada fila devuelta y podría ejecutarse más veces si se aplican otras condiciones después de que se aplique la condición que contiene la subconsulta correlacionada.
Perdone el ejemplo creado y la sintaxis de Oracle, pero supongamos que desea encontrar a todos los empleados que han sido contratados en cualquiera de sus tiendas desde la última vez que la tienda hizo menos de $ 10,000 de ventas en un día.
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 subconsulta en este ejemplo está correlacionada con la consulta externa por store_id y se ejecutaría para cada empleado en su sistema. Una forma en que esta consulta podría optimizarse es mover la subconsulta a una vista en línea.
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
En este ejemplo, la consulta en la cláusula from ahora es una vista en línea (de nuevo, una sintaxis específica de Oracle) y solo se ejecuta una vez. Dependiendo de su modelo de datos, esta consulta probablemente se ejecutará mucho más rápido. Se desempeñaría mejor que la primera consulta a medida que crecía el número de empleados. La primera consulta podría funcionar mejor si hubiera pocos empleados y muchas tiendas (y quizás muchas de las tiendas no tenían empleados) y la tabla de ventas diarias se indexó en store_id. Este no es un escenario probable, pero muestra cómo una consulta correlacionada podría funcionar mejor que una alternativa.
He visto a desarrolladores junior correlacionar subconsultas muchas veces y generalmente ha tenido un impacto severo en el rendimiento. Sin embargo, al eliminar una subconsulta correlacionada, asegúrese de consultar el plan de explicación antes y después para asegurarse de que no esté empeorando el rendimiento.
No entender cómo funciona un DBMS bajo el capó.
No puedes conducir un palo correctamente sin entender cómo funciona un embrague. Y no puede entender cómo usar una base de datos sin entender que en realidad solo está escribiendo un archivo en su disco duro.
Específicamente:
¿Sabes lo que es un índice agrupado? ¿Pensaste en ello cuando diseñaste tu esquema?
¿Sabes cómo usar correctamente los índices? ¿Cómo reutilizar un índice? ¿Sabes lo que es un índice de cobertura?
Muy bien, tienes índices. ¿Qué tan grande es 1 fila en su índice? ¿Cuán grande será el índice cuando tengas muchos datos? ¿Cabe eso fácilmente en la memoria? Si no lo es, es inútil como índice.
¿Alguna vez has usado EXPLAIN en MySQL? Genial. Ahora sé honesto contigo mismo: ¿Entendiste incluso la mitad de lo que viste? No, probablemente no lo hiciste. Arregla eso.
¿Entiendes el caché de consultas? ¿Sabes qué hace que una consulta no pueda guardarse en caché?
¿Estás utilizando MyISAM? Si NECESITA una búsqueda de texto completo, MyISAM es una mierda de todos modos. Usa la esfinge. Luego cambia a Inno.
Principales bases de datos de diseño y errores de programación cometidos por los desarrolladores.
Diseño y uso de bases de datos egoístas. Los desarrolladores a menudo tratan la base de datos como su almacén personal de objetos persistentes sin tener en cuenta las necesidades de otros interesados en los datos. Esto también se aplica a los arquitectos de aplicaciones. El mal diseño de la base de datos y la integridad de los datos dificulta a los terceros que trabajan con los datos y puede aumentar sustancialmente los costos del ciclo de vida del sistema. Los informes y MIS tienden a ser un primo pobre en el diseño de la aplicación y solo se realizan a posteriori.
Abusando de los datos desnormalizados. Exagerar los datos desnormalizados y tratar de mantenerlos dentro de la aplicación es una receta para los problemas de integridad de los datos. Utilice la desnormalización con moderación. No querer agregar una unión a una consulta no es una excusa para la desnormalización.
Miedo de escribir SQL. SQL no es ciencia espacial y en realidad es bastante bueno en hacer su trabajo. Las capas de mapeo O / R son bastante buenas para hacer el 95% de las consultas que son simples y se ajustan bien a ese modelo. A veces, SQL es la mejor manera de hacer el trabajo.
Políticas dogmáticas ''No hay procedimientos almacenados''. Independientemente de si cree que los procedimientos almacenados son malos, este tipo de actitud dogmática no tiene cabida en un proyecto de software.
No entendiendo el diseño de la base de datos. La normalización es tu amiga y no es ciencia espacial. La unión y la cardinalidad son conceptos bastante simples: si estás involucrado en el desarrollo de aplicaciones de base de datos, realmente no hay excusa para no entenderlos.
Odio que los desarrolladores utilicen declaraciones de selección anidadas o incluso funcionen para devolver el resultado de una declaración de selección dentro de la parte "SELECCIONAR" de una consulta.
De hecho, me sorprende que no vea esto en ningún otro lugar aquí, tal vez lo pasé por alto, aunque @adam tiene un problema similar indicado.
Ejemplo:
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
En este escenario, si MyTable devuelve 10000 filas, el resultado es como si la consulta simplemente ejecutara 20001 consultas, ya que tuvo que ejecutar la consulta inicial y consultar cada una de las otras tablas una vez por cada línea de resultado.
Los desarrolladores pueden salirse con la suya trabajando en un entorno de desarrollo donde solo están devolviendo unas pocas filas de datos y las tablas secundarias generalmente solo tienen una pequeña cantidad de datos, pero en un entorno de producción, este tipo de consulta puede ser exponencialmente costoso y más Los datos se agregan a las tablas.
Un ejemplo mejor (no necesariamente perfecto) sería algo como:
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
Esto permite que los optimizadores de la base de datos mezclen los datos juntos, en lugar de volver a consultar cada registro de la tabla principal y generalmente encuentro que cuando tengo que arreglar el código donde se ha creado este problema, generalmente termino aumentando la velocidad de las consultas en un 100% o más mientras que simultáneamente reduce el uso de CPU y memoria.
Para bases de datos basadas en SQL:
- No aprovechar los ÍNDICES CLUSTRADOS o elegir la (s) columna (s) equivocada para CLUSTER.
- No usar un tipo de datos SERIAL (autonumber) como una CLAVE PRINCIPAL para unirse a una KEY FOREIGN (INT) en una relación de tabla padre / hijo.
- No ACTUALIZAR ESTADÍSTICAS en una tabla cuando muchos registros han sido INSERTADOS o BORRADOS.
- No reorganizar (es decir, descargar, soltar, volver a crear, cargar y volver a indexar) las tablas cuando se han insertado o eliminado muchas filas (algunos motores mantienen físicamente las filas eliminadas en una tabla con un indicador de eliminación)
- No aprovechar el FRAGMENTO EN EXPRESIÓN (si se admite) en tablas grandes que tienen altas tasas de transacción.
- ¡Elegir el tipo de datos incorrecto para una columna!
- No elegir un nombre de columna adecuado.
- No agregar nuevas columnas al final de la tabla.
- No crear índices adecuados para soportar consultas de uso frecuente.
- creando índices en columnas con pocos valores posibles y creando índices innecesarios.
... más por agregar.
Tratar la base de datos solo como un mecanismo de almacenamiento (es decir, una biblioteca de colecciones glorificada) y, por lo tanto, subordinada a su aplicación (ignorando otras aplicaciones que comparten los datos)
Aquí hay un enlace al video llamado '' Errores clásicos de desarrollo de bases de datos y cinco maneras de superarlos '' por Scott Walz
El error más común que he visto en veinte años: no planear con anticipación. Muchos desarrolladores crearán una base de datos y tablas, y luego modificarán y expandirán continuamente las tablas a medida que desarrollan las aplicaciones. El resultado final suele ser un desastre, ineficiente y difícil de limpiar o simplificar más adelante.
Esto se ha dicho antes, pero: índices, índices, índices . He visto tantos casos de aplicaciones web empresariales de bajo rendimiento que se corrigieron simplemente haciendo un poco de perfil (para ver qué tablas estaban siendo afectadas mucho) y luego agregando un índice en esas tablas. Esto ni siquiera requiere mucho conocimiento de escritura de SQL, y la recompensa es enorme.
Evita la duplicación de datos como la plaga. Algunas personas abogan por que una pequeña duplicación no duela, y mejorará el rendimiento. Oye, no estoy diciendo que tengas que torturar tu esquema en Tercera Forma Normal, hasta que sea tan abstracto que ni siquiera los DBA saben lo que está pasando. Simplemente entienda que siempre que duplique un conjunto de nombres, códigos postales o códigos de envío, las copias se desincronizarán eventualmente. Pasará. Y luego te patearás mientras ejecutas el script de mantenimiento semanal.
Y, por último, utilice una convención de nomenclatura clara, coherente e intuitiva. De la misma manera que un fragmento de código bien escrito debe ser legible, un buen esquema o consulta SQL debe ser legible y prácticamente decirle qué está haciendo, incluso sin comentarios. Te agradecerás en seis meses, cuando tengas que hacer mantenimiento en las mesas. "SELECT account_number, billing_date FROM national_accounts"
es infinitamente más fácil trabajar con "SELECT ACCNTNBR, BILLDAT FROM NTNLACCTS".
No hacer el nivel correcto de normalización . Desea asegurarse de que los datos no estén duplicados y de que esté dividiendo los datos según sea necesario. También debe asegurarse de no estar siguiendo la normalización demasiado, ya que esto afectará el rendimiento.
No presta suficiente atención a la gestión de las conexiones de base de datos en su aplicación. Luego descubre que la aplicación, la computadora, el servidor y la red están obstruidos.
No tener una comprensión del modelo de concurrencia de bases de datos y cómo esto afecta el desarrollo. Es fácil agregar índices y modificar las consultas después del hecho. Sin embargo, las aplicaciones diseñadas sin la debida consideración para los puntos de acceso, la contención de recursos y el funcionamiento correcto (¡asumiendo que lo que acaba de leer todavía es válido!) Pueden requerir cambios significativos dentro de la base de datos y el nivel de aplicación para corregirlos más adelante.
a) Valores de consulta de codificación fija en la cadena
b) Colocación del código de consulta de la base de datos en la acción "OnButtonPress" en una aplicación de Windows Forms
He visto ambas cosas.
No tomar una copia de seguridad antes de solucionar algún problema dentro de la base de datos de producción.
Uso de comandos DDL en objetos almacenados (como tablas, vistas) en procedimientos almacenados.
Temor de usar procedimientos almacenados o temor de usar consultas ORM donde sea más eficiente / apropiado de usar.
Ignorar el uso de un perfilador de base de datos, que le puede decir exactamente en qué se está convirtiendo finalmente su consulta ORM y, por lo tanto, verificar la lógica o incluso la depuración cuando no se usa ORM.
- Descartar un ORM como Hibernate de la mano, por razones como "es demasiado mágico" o "no está en mi base de datos".
- Confiar demasiado en un ORM como Hibernate y tratar de calzarlo donde no sea apropiado.