{"id":21331,"date":"2026-09-12T15:01:49","date_gmt":"2026-09-12T13:01:49","guid":{"rendered":"https:\/\/webhosting.de\/mariadb-optimizer-trace-sql-performance-analyse-datenbank\/"},"modified":"2026-09-12T15:01:49","modified_gmt":"2026-09-12T13:01:49","slug":"mariadb-optimizador-rastreo-analisis-del-rendimiento-de-sql-base-de-datos","status":"publish","type":"post","link":"https:\/\/webhosting.de\/es\/mariadb-optimizer-trace-sql-performance-analyse-datenbank\/","title":{"rendered":"Rastreo del optimizador de MariaDB: comprender las consultas SQL en detalle"},"content":{"rendered":"<p>Con el \u00aboptimizer trace\u00bb de MariaDB puedo comprender, paso a paso, por qu\u00e9 el optimizador elige un plan concreto y qu\u00e9 variantes descarta. Este rastro JSON me muestra <strong>Decisiones<\/strong> sobre costes, orden de las uniones y filtros, para poder adaptar las consultas SQL de forma espec\u00edfica.<\/p>\n\n<h2>Puntos centrales<\/h2>\n\n<ul>\n  <li><strong>Transparencia<\/strong>: Un seguimiento basado en JSON explica las reescrituras, los costes y los planes descartados.<\/li>\n  <li><strong>Enfoque<\/strong>: \u00abjoin_preparation\u00bb y \u00abjoin_optimization\u00bb proporcionan la informaci\u00f3n m\u00e1s relevante.<\/li>\n  <li><strong>Sistema de control<\/strong>: Las variables de sesi\u00f3n reducen la sobrecarga y el consumo de memoria.<\/li>\n  <li><strong>Flujo de trabajo<\/strong>: EXPLAIN\/ANALYZE para el plan, Trace para el \u201eporqu\u00e9\u201c.<\/li>\n  <li><strong>Ventajas pr\u00e1cticas<\/strong>: Ajustar de forma fundamentada los \u00edndices, las estad\u00edsticas y el orden de las uniones.<\/li>\n<\/ul>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/mariadb-optimizer-trace-0294.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>\u00bfQu\u00e9 es el rastreo del optimizador de MariaDB?<\/h2>\n\n<p>Desde la versi\u00f3n 10.4, MariaDB incluye un <strong>Optimizador<\/strong> Trace, que documenta en formato JSON cada fase importante de optimizaci\u00f3n de una instrucci\u00f3n SELECT, UPDATE o DELETE. En \u00e9l puedo ver c\u00f3mo el motor ampl\u00eda las consultas, normaliza las condiciones y, finalmente, determina el orden de las uniones, incluidos los accesos a los \u00edndices. Esta visi\u00f3n va mucho m\u00e1s all\u00e1 de EXPLAIN, que muestra principalmente el plan final, y revela las alternativas descartadas junto con sus justificaciones. El rastro se almacena en memoria para cada conexi\u00f3n y est\u00e1 disponible a trav\u00e9s de <code>information_schema.OPTIMIZER_TRACE<\/code> listo. As\u00ed obtengo una explicaci\u00f3n completa y legible por m\u00e1quina de la estructura interna <strong>Pasos<\/strong>, que han dado lugar a un plan de ejecuci\u00f3n.<\/p>\n\n<h2>Activar y leer el rastreo del optimizador<\/h2>\n\n<p>Activo la funci\u00f3n de forma espec\u00edfica en cada sesi\u00f3n para poder realizar diagn\u00f3sticos sin una sobrecarga general y tener un control total sobre <strong>Memoria<\/strong> tengo. Normalmente pongo <code>SET SESSION optimizer_trace = 'enabled=on';<\/code> y si es necesario <code>SET SESSION optimizer_trace_max_mem_size = 1048576;<\/code> o superior, si el rastreo es extenso. A continuaci\u00f3n, ejecuto la consulta sospechosa y leo el rastreo con <code>SELECT * FROM information_schema.OPTIMIZER_TRACE LIMIT 1\\G;<\/code>. Importante: la tabla solo almacena la \u00faltima consulta de la conexi\u00f3n activa, y tengo en cuenta campos como <code>MISSING_BYTES_BEYOND_MAX_MEM_SIZE<\/code> o <code>INSUFFICIENT_PRIVILEGES<\/code> para obtener indicaciones de diagn\u00f3stico. Este m\u00e9todo de trabajo mantiene el entorno de producci\u00f3n optimizado y facilita el an\u00e1lisis <strong>preciso<\/strong>.<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Variable\/Campo<\/th>\n      <th>Prop\u00f3sito<\/th>\n      <th>Valor de ejemplo<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code>optimizer_trace<\/code><\/td>\n      <td>Activa el seguimiento por sesi\u00f3n<\/td>\n      <td><code>'enabled=on'<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td><code>optimizer_trace_max_mem_size<\/code><\/td>\n      <td>Capacidad m\u00e1xima de almacenamiento por traza<\/td>\n      <td><code>1048576<\/code> (1 MB)<\/td>\n    <\/tr>\n    <tr>\n      <td><code>OPTIMIZER_TRACE.QUERY<\/code><\/td>\n      <td>Sentencia SQL original<\/td>\n      <td><code>SELECT ...<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td><code>OPTIMIZER_TRACE.TRACE<\/code><\/td>\n      <td>Documento JSON de la optimizaci\u00f3n<\/td>\n      <td>Texto JSON<\/td>\n    <\/tr>\n    <tr>\n      <td><code>MISSING_BYTES_BEYOND_MAX_MEM_SIZE<\/code><\/td>\n      <td>Bytes recortados cuando el rastreo es demasiado grande<\/td>\n      <td>0 o cantidad<\/td>\n    <\/tr>\n    <tr>\n      <td><code>INSUFFICIENT_PRIVILEGES<\/code><\/td>\n      <td>\u00bfEs suficiente con el permiso de lectura?<\/td>\n      <td>0 o 1<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/mariadb_optimizer_besprechung_5829.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Estructura JSON: join_preparation y join_optimization<\/h2>\n\n<p>La estructura JSON se divide en los siguientes bloques: <code>preparaci\u00f3n de la uni\u00f3n<\/code> y <code>optimizaci\u00f3n de uniones<\/code>, que reviso en primer lugar porque son las m\u00e1s importantes <strong>Notas<\/strong> suministrar. En el apartado <code>preparaci\u00f3n de la uni\u00f3n<\/code> Reconozco la consulta ampliada (<code>expanded_query<\/code>) y compruebo si el motor ha transformado las condiciones o las proyecciones, y de qu\u00e9 manera. El segundo bloque <code>optimizaci\u00f3n de uniones<\/code> registra las estimaciones de l\u00edneas, los planes analizados, el orden de uni\u00f3n seleccionado y la incorporaci\u00f3n de partes selectivas de la cl\u00e1usula WHERE a las tablas. Los sub\u00e1rboles resultan especialmente \u00fatiles <code>rows_estimation<\/code>, <code>planes_de_ejecuci\u00f3n_considerados<\/code> y <code>asignaci\u00f3n de condiciones a tablas<\/code>, ya que hacen referencia directa a las hip\u00f3tesis de costes y a los criterios de filtrado. De este modo, puedo detectar r\u00e1pidamente d\u00f3nde hay errores de valoraci\u00f3n o situaciones desfavorables <strong>\u00cdndices<\/strong> dar lugar a planes que no son \u00f3ptimos.<\/p>\n\n<h2>Comparaci\u00f3n con EXPLAIN y ANALYZE<\/h2>\n\n<p>Para realizar una evaluaci\u00f3n completa, combino EXPLAIN, ANALYZE y el <strong>Rastrear<\/strong> siguiendo un procedimiento fijo. Primero utilizo <code>EXPLICAR<\/code> o <code>EXPLAIN FORMAT=JSON<\/code>, para ver el plan seleccionado y las rutas clave. A continuaci\u00f3n, establezco <code>EXPLAIN ANALYZE<\/code> para obtener datos reales sobre el tiempo de ejecuci\u00f3n y valores de recuento, como bucles y l\u00edneas filtradas. Si a\u00fan tengo dudas, activo el seguimiento del optimizador y compruebo qu\u00e9 variantes ha evaluado y descartado el optimizador. Este art\u00edculo me ofrece una introducci\u00f3n concisa sobre c\u00f3mo interpretar los resultados: <a href=\"https:\/\/webhosting.de\/es\/interpretar-consultas-mysql-explain-analyze-y-optimizacion-de-consultas\/\">Entender EXPLAIN ANALYZE<\/a>, al que recurro como complemento cuando es necesario.<\/p>\n\n<h2>Comprender las decisiones de planificaci\u00f3n: costes, cardinalidades, filtros<\/h2>\n\n<p>La l\u00f3gica de la toma de decisiones se basa en las cardinalidades, los modelos de costes y la ubicaci\u00f3n de <strong>Filtro<\/strong> siguiendo el plan. En el rastreo veo, para cada secuencia de uniones analizada, qu\u00e9 conjuntos de filas espera el motor y c\u00f3mo calcula a partir de ellos el coste total. Compruebo si unas estad\u00edsticas obsoletas o unas correlaciones desfavorables provocan que se subestimen los escaneos por rango y se den prioridad a los escaneos completos. Adem\u00e1s, compruebo si el motor aplica las condiciones WHERE a la tabla m\u00e1s selectiva con la suficiente antelaci\u00f3n como para reducir los costosos pasos de uni\u00f3n. De este modo, puedo llegar a conclusiones s\u00f3lidas sobre por qu\u00e9 se ha elegido un plan y c\u00f3mo puedo mejorarlo con <strong>\u00cdndices<\/strong>, las reescrituras o el mantenimiento de las estad\u00edsticas.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/mariadb-optimizer-trace-sql-4271.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Ejercicio pr\u00e1ctico: seguimiento de una consulta de filtro sencilla<\/h2>\n\n<p>En <code>SELECT * FROM t1 WHERE a &lt; 10<\/code> Lo compruebo en <code>preparaci\u00f3n de la uni\u00f3n<\/code>, si el motor ha ampliado la proyecci\u00f3n y, en su caso, ha consolidado condiciones, lo que me da una primera <strong>Indicadores<\/strong> muestra. A continuaci\u00f3n, veo en el bloque <code>rows_estimation<\/code>, cu\u00e1ntas l\u00edneas utiliza el motor para el Range-Scan en <code>a<\/code> en comparaci\u00f3n con el escaneo completo de la tabla. Si se detectan valores poco realistas, suelo interpretarlo como un indicio de que las estad\u00edsticas est\u00e1n desactualizadas o de que faltan histogramas. En la secci\u00f3n <code>planes_de_ejecuci\u00f3n_considerados<\/code> A continuaci\u00f3n, compruebo si el acceso al \u00edndice se ha calculado realmente como m\u00e1s econ\u00f3mico que el escaneo completo. Por \u00faltimo, muestra <code>asignaci\u00f3n de condiciones a tablas<\/code>, si la condici\u00f3n selectiva se aplica a <code>a<\/code> se pone en marcha antes de lo previsto, lo que reduce considerablemente la duraci\u00f3n <strong>disminuye<\/strong>.<\/p>\n\n<h2>Funciones JSON: extraer fragmentos de forma selectiva<\/h2>\n\n<p>Como el rastro est\u00e1 en formato JSON, filtro de forma espec\u00edfica sub\u00e1rboles con <code>JSON_EXTRACT<\/code> y elaboro peque\u00f1os an\u00e1lisis para datos recurrentes <strong>Muestra<\/strong>. Por ejemplo, solo reviso la lista de planes considerados para comprobar si determinados \u00f3rdenes de uni\u00f3n fallan sistem\u00e1ticamente. Del mismo modo, extraigo los campos de costes de los principales candidatos y los comparo con los datos de ANALYZE para detectar suposiciones err\u00f3neas. Mediante vistas sencillas o procedimientos almacenados, automatizo estas comprobaciones para mis sesiones de diagn\u00f3stico. De esta forma, me construyo un sencillo <strong>Monitoreo<\/strong> para las decisiones del optimizador sin activar el seguimiento permanente.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/mariadb_optimizer_trace_4729.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Casos de uso t\u00edpicos y ventajas<\/h2>\n\n<p>Recurro al trace cuando EXPLAIN muestra un escaneo completo inesperado y quiero averiguar el motivo del rechazo de un <strong>\u00cdndice<\/strong> quiero averiguar. Asimismo, el rastreo me proporciona, en el caso de muchas tablas, la justificaci\u00f3n del orden de uni\u00f3n elegido, lo que me indica el camino hacia planes alternativos. Al cambiar de versi\u00f3n, guardo los registros de seguimiento anteriores y posteriores a la actualizaci\u00f3n para evaluar los cambios en el comportamiento del optimizador. Para cuestiones estrat\u00e9gicas de ajuste, esta visi\u00f3n general me ayuda a <a href=\"https:\/\/webhosting.de\/es\/explicacion-interna-del-optimizador-de-consultas-de-mariadb-perspectivas-sobre-el-ajuste-de-sql\/\">mecanismos internos del optimizador<\/a>, que relaciono con los resultados del rastreo. As\u00ed decido de forma estructurada si debo modificar los \u00edndices, las estad\u00edsticas o la formulaci\u00f3n de las consultas para <strong>tornillo de ajuste<\/strong> pongo.<\/p>\n\n<h2>Buenas pr\u00e1cticas para la producci\u00f3n<\/h2>\n\n<p>Activo el seguimiento de forma sistem\u00e1tica como <strong>Sesi\u00f3n<\/strong>-Configuraci\u00f3n y finalizo el diagn\u00f3stico correctamente en cuanto tenga datos suficientes. Para trazas grandes, aumento <code>optimizer_trace_max_mem_size<\/code> solo de forma temporal y, despu\u00e9s, vuelvo a establecer el valor en un nivel bajo. Antes de compartir archivos JSON, oculto las constantes sensibles, los textos de los comentarios o los indicadores clave de negocio. Utilizo el rastreo de forma selectiva como herramienta de diagn\u00f3stico, mientras que para la supervisi\u00f3n continua prefiero los registros de consultas lentas, las vistas de rendimiento o los perfiladores externos. Esta disciplina mantiene los sistemas optimizados y evita el <strong>Sobrecarga<\/strong> en el d\u00eda a d\u00eda.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/mariadb_optimizer_trace_3874.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Optimizer Trace en la combinaci\u00f3n de herramientas<\/h2>\n\n<p>Para lograr un ajuste integral, represento la cadena formada por la comprensi\u00f3n del plan, el an\u00e1lisis de causas y la medici\u00f3n del sistema, y relaciono los <strong>Hallazgos<\/strong>. EXPLAIN me muestra el plan, ANALYZE confirma los costes reales y el rastreo proporciona los motivos que hay detr\u00e1s de la decisi\u00f3n. Al mismo tiempo, analizo los conceptos del plan de ejecuci\u00f3n de consultas para identificar patrones en la selecci\u00f3n de claves, las cardinalidades y las estrategias de uni\u00f3n. Un buen complemento para esta perspectiva es la visi\u00f3n general concisa sobre <a href=\"https:\/\/webhosting.de\/es\/planes-de-ejecucion-de-consultas-de-bases-de-datos-que-alojan-informacion-sobre-el-rendimiento-de-la-optimizacion\/\">Planes de ejecuci\u00f3n de consultas<\/a>, al que recurro cuando tengo dudas sobre arquitectura. De ah\u00ed deduzco conclusiones s\u00f3lidas <strong>Prioridades<\/strong> para el trabajo con \u00edndices, reescrituras y par\u00e1metros.<\/p>\n\n<h2>Profundicemos en el tema: an\u00e1lisis de rango y elecci\u00f3n de claves<\/h2>\n\n<p>A menudo hay un bloqueo en el rastreo <code>an\u00e1lisis de rango<\/code> para cada tabla, en la que puedo identificar qu\u00e9 \u00edndices eran aptos para accesos de tipo \u201erange\u201c, \u201eref\u201c o \u201eeq-ref\u201c. El optimizador compara all\u00ed alternativas como \u00abrange en idx_a\u00bb, \u00abrange en idx_b\u00bb o \u00abfull scan\u00bb, les asigna costes y el n\u00famero de filas esperadas, y se\u00f1ala la opci\u00f3n ganadora. Si veo que se ha descartado un \u00edndice adecuado debido a su elevado coste, lo siguiente que hago es examinar las selectividades y estad\u00edsticas subyacentes. Si las suposiciones no son correctas, puede que un <code>ANALIZAR TABLA<\/code> (en su caso, con estad\u00edsticas persistentes) o la creaci\u00f3n de un <strong>\u00cdndice de cobertura<\/strong> anular la decisi\u00f3n.<\/p>\n\n<p>Tambi\u00e9n resulta \u00fatil analizar las divisiones de los \u00edndices compuestos: el rastreo documenta si la condici\u00f3n solo utiliza la primera columna del \u00edndice o si hay predicados adicionales que pueden aplicarse y otras columnas clave pasan a ser efectivas. A partir de ah\u00ed, decido si reformulo los predicados (por ejemplo, evitando funciones) o si ampl\u00edo el \u00edndice de tal forma que cubra los filtros y ordenaciones habituales.<\/p>\n\n<h2>Las uniones en detalle: semionciones, BKA\/MRR y b\u00faferes de uni\u00f3n<\/h2>\n\n<p>En las consultas con varias tablas, las secciones de seguimiento muestran si se ha tenido en cuenta alguna estrategia de semijunci\u00f3n y, en caso afirmativo, cu\u00e1l (por ejemplo, FirstMatch, DuplicateWeedout, LooseScan o Materialization). All\u00ed puedo ver por qu\u00e9 se ha descartado una variante, por ejemplo, debido a unos costes de materializaci\u00f3n elevados o a una selectividad demasiado baja. Tambi\u00e9n <strong>Acceso a claves por lotes (BKA)<\/strong> y <strong>Lectura multirrango (MRR)<\/strong> aparecen en el rastreo, siempre que est\u00e9n activadas. Estas t\u00e9cnicas agrupan las b\u00fasquedas de claves y mejoran la localidad de la cach\u00e9. Si BKA\/MRR no aparecen en el rastreo, compruebo <code>optimizer_switch<\/code> y par\u00e1metros como <code>join_cache_level<\/code>. En cargas de trabajo con numerosas b\u00fasquedas aleatorias de claves, esto permite acelerar notablemente la fase de uni\u00f3n, lo cual se puede comprobar con EXPLAIN ANALYZE.<\/p>\n\n<p>Adem\u00e1s, el tama\u00f1o y el tipo del b\u00fafer de uni\u00f3n son fundamentales: el traza permite ver si se han ejecutado variantes de bucle anidado con o sin b\u00fafer y en qu\u00e9 punto se aplican los filtros. Eval\u00fao si la opci\u00f3n m\u00e1s eficiente es a\u00f1adir \u00edndices adicionales en las claves de uni\u00f3n o reescribir la consulta para reducir los resultados intermedios, en lugar de aumentar el tama\u00f1o de los b\u00faferes.<\/p>\n\n<h2>Subconsultas, tablas derivadas y vistas<\/h2>\n\n<p>En <code>preparaci\u00f3n de la uni\u00f3n<\/code> Creo que, si las subconsultas en forma de EXISTS\/IN en <strong>Semijunciones<\/strong> se transformaron (<code>in_to_exists<\/code>), si las tablas derivadas se han fusionado (<code>derived_merge<\/code>) o se han materializado y si <strong>Condici\u00f3n Pushdown<\/strong> hasta las tablas derivadas. Estos pasos son fundamentales, ya que omitir una fusi\u00f3n puede provocar una materializaci\u00f3n costosa. Si en el seguimiento veo repetidamente decisiones de materializaci\u00f3n con un coste elevado, compruebo si existe una <code>STRAIGHT_JOIN<\/code>, una sugerencia o una reorganizaci\u00f3n de la consulta (por ejemplo, expresiones de tabla com\u00fan con filtros espec\u00edficos) que lleve al motor a adoptar una estrategia m\u00e1s adecuada. En el caso de las vistas, compruebo si el optimizador desglosa suficientemente el contenido de la vista o si faltan \u00edndices adicionales en la tabla subyacente.<\/p>\n\n<h2>Partici\u00f3n y poda<\/h2>\n\n<p>En el caso de las tablas particionadas, el rastreo muestra qu\u00e9 particiones se han excluido en funci\u00f3n de las claves de partici\u00f3n y los predicados (<strong>Poda de particiones<\/strong>). Si no se produce la poda esperada, es una se\u00f1al de que hay que formular los filtros antes y de forma m\u00e1s selectiva en funci\u00f3n de la clave de partici\u00f3n. Adem\u00e1s, presto atenci\u00f3n a la interacci\u00f3n entre la partici\u00f3n y los \u00edndices: si faltan \u00edndices locales o globales, el motor puede examinar un n\u00famero excesivo de filas a pesar de la poda, lo que se refleja en el rastreo mediante unos elevados costes de exploraci\u00f3n.<\/p>\n\n<h2>Verificar de forma espec\u00edfica las sugerencias, las especificaciones de \u00edndice y el par\u00e1metro `optimizer_switch`<\/h2>\n\n<p>Utilizo el Trace para comprobar el efecto de las sugerencias y los modificadores de par\u00e1metros para <strong>ocupa<\/strong>. Si pongo, por ejemplo,. <code>\u00cdNDICE DE FUERZA<\/code> o una sugerencia del optimizador, puedo ver en el rastreo si la alternativa se ha forzado realmente y c\u00f3mo se ha evaluado. A trav\u00e9s de <code>optimizer_switch<\/code> Puedo activar o desactivar estrategias de forma temporal (por ejemplo, para decisiones de semijoin, index_merge o derived_merge). El registro me sirve entonces como prueba para comprobar si el motor ha aceptado las especificaciones o si siguen prevaleciendo otras restricciones (por ejemplo, las cardinalidades). Opcionalmente, utilizo indicadores de formato como <code>one_line<\/code> o <code>end_markers<\/code> en <code>optimizer_trace<\/code>-String, para adaptar la legibilidad a mi herramienta de an\u00e1lisis.<\/p>\n\n<h2>Update\/DELETE y rutas de escritura<\/h2>\n\n<p>El rastreo del optimizador no se limita a las sentencias SELECT. En las sentencias UPDATE y DELETE tambi\u00e9n puedo ver c\u00f3mo se eligen las rutas de acceso y si los filtros se aplican con la suficiente antelaci\u00f3n como para mantener reducido el n\u00famero de filas afectadas. Compruebo si un filtro WHERE no es sargable o si la falta de un \u00edndice provoca una fase de exploraci\u00f3n amplia antes de que se ejecute la modificaci\u00f3n propiamente dicha. A partir del rastreo, deduzco si un \u00edndice compacto (por ejemplo, solo las columnas necesarias) evita accesos innecesarios de ida y vuelta y, con ello, reduce los bloqueos y el volumen de registro.<\/p>\n\n<h2>Seguridad, privilegios y sentencias preparadas<\/h2>\n\n<p>Para poder leer el registro completo, necesito los privilegios de objeto suficientes; si no los tengo, el campo indica <code>INSUFFICIENT_PRIVILEGES<\/code> Restricciones. Por eso, en entornos cercanos a la producci\u00f3n utilizo los mismos datos de acceso que la aplicaci\u00f3n o una cuenta de diagn\u00f3stico con permisos especiales. En el caso de las sentencias preparadas, el rastreo suele mostrar la forma optimizada con los par\u00e1metros ya vinculados, lo que me permite evaluar la selectividad sin revelar constantes sensibles. Si tengo que compartir los rastreos, enmascaro los valores de los par\u00e1metros o los sustituyo por rangos representativos para cumplir con los requisitos de protecci\u00f3n de datos.<\/p>\n\n<h2>Automatizaci\u00f3n: registrar, diferenciar y documentar trazas<\/h2>\n\n<p>Para que los an\u00e1lisis sean reproducibles, guardo trazas de forma aleatoria en una tabla de diagn\u00f3stico y les a\u00f1ado metadatos como el esquema, la versi\u00f3n, las variables de sesi\u00f3n y la marca de tiempo. De este modo, puedo comparar los resultados antes y despu\u00e9s de los cambios en los \u00edndices o las actualizaciones de versi\u00f3n <strong>diffen<\/strong>, qu\u00e9 decisiones se han pospuesto. Resulta pr\u00e1ctico agrupar los bloques <code>planes_de_ejecuci\u00f3n_considerados<\/code> y <code>rows_estimation<\/code> guardarlas por separado para poder comparar r\u00e1pidamente las variaciones en los costes. Unas peque\u00f1as consultas auxiliares me permiten extraer el orden de uni\u00f3n seleccionado y los costes calculados, por ejemplo, con <code>JSON_EXTRACT(TRACE, '$.join_optimization.considered_execution_plans')<\/code> \u2013 y guardamos el resultado junto con los resultados de EXPLAIN y ANALYZE. De este modo se crea una documentaci\u00f3n fiable para cada paso del proceso de optimizaci\u00f3n.<\/p>\n\n<h2>Limitaciones, particularidades de cada versi\u00f3n y comparaci\u00f3n con MySQL<\/h2>\n\n<p>Las estructuras clave de la traza se basan en MySQL, aunque los detalles y los nombres de los campos pueden variar ligeramente en funci\u00f3n de la versi\u00f3n de MariaDB. Por eso me centro en la <strong>sem\u00e1nticos<\/strong> Secciones (Rewrites, Rows-Estimation, planes analizados, Condition-Attachments), en lugar de dejarme confundir por diferencias superficiales. Importante: en MariaDB, la atenci\u00f3n se centra en la \u00faltima instrucci\u00f3n de la conexi\u00f3n activa. Por lo tanto, quien analice muchas sentencias consecutivas debe leerlas inmediatamente despu\u00e9s de su ejecuci\u00f3n o de forma automatizada mediante un hook, para que no se sobrescriban rastros relevantes. En el caso de archivos JSON muy grandes, tengo en cuenta los requisitos de memoria y comprendo <code>MISSING_BYTES_BEYOND_MAX_MEM_SIZE<\/code> como una invitaci\u00f3n a aumentar temporalmente el l\u00edmite y volver a ejecutar el an\u00e1lisis.<\/p>\n\n<h2>Extracciones concretas de JSON para el d\u00eda a d\u00eda<\/h2>\n\n<p>Para terminar, unos cuantos fragmentos breves que suelo utilizar a menudo en la pr\u00e1ctica para ir directamente al grano:<\/p>\n\n<ul>\n  <li>Orden de uni\u00f3n seleccionado y listas de candidatos: extraigo los prefijos del plan y la tabla asociada a cada uno de ellos para poder seguir el proceso de toma de decisiones.<\/li>\n  <li>Alternativas de rangos y costes: extraigo la lista de \u00edndices evaluados para las tablas m\u00e1s selectivas, con el fin de evaluar con precisi\u00f3n las reescrituras o los nuevos \u00edndices.<\/li>\n  <li>Filtros aplicados al principio: Estoy leyendo el <code>asignaci\u00f3n de condiciones a tablas<\/code>-Secciones, para garantizar que los predicados potentes se sit\u00faen lo m\u00e1s cerca posible de la fuente de datos.<\/li>\n<\/ul>\n\n<p>Con unas pocas vistas de estas extracciones, dispongo de una \u201elente de lectura\u201c sencilla para las decisiones del optimizador, que activo cuando es necesario en las sesiones de diagn\u00f3stico y vuelvo a desactivar despu\u00e9s.<\/p>\n\n<h2>Tropiezos frecuentes y resoluci\u00f3n de problemas<\/h2>\n\n<p>Si faltan histogramas o las estad\u00edsticas est\u00e1n desactualizadas, las estimaciones son err\u00f3neas y dan lugar a <strong>Planes<\/strong> con escaneos completos innecesarios. Si observo cardinalidades muy dispares en el rastreo, actualizo las estad\u00edsticas, establezco \u00edndices adecuados o redacto filtros que se puedan aplicar de forma selectiva. Detecto los rastreos demasiado escuetos a trav\u00e9s de <code>MISSING_BYTES_BEYOND_MAX_MEM_SIZE<\/code> y respondo aumentando temporalmente el l\u00edmite. Si ANALYZE ofrece mejores tiempos de ejecuci\u00f3n para una ruta alternativa, compruebo en el rastreo qu\u00e9 factor de coste ha favorecido la variante elegida. De este modo, voy subsanando poco a poco las lagunas de conocimiento y consigo <strong>Claridad<\/strong> sobre la l\u00f3gica de la toma de decisiones.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/mariadb-optimizer-trace-4829.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Brevemente resumido<\/h2>\n\n<p>El MariaDB Optimizer Trace me explica, en un documento JSON, c\u00f3mo el motor reformula las consultas, estima el n\u00famero de filas, compara planes y, finalmente, genera una <strong>Secuencia<\/strong> selecciona. Lo activo en cada sesi\u00f3n, leo la pista y compruebo <code>preparaci\u00f3n de la uni\u00f3n<\/code> y <code>optimizaci\u00f3n de uniones<\/code> y relaciono estos hallazgos con EXPLAIN\/ANALYZE. A partir de los motivos por los que se rechazan los \u00edndices, los filtros tard\u00edos o las estimaciones err\u00f3neas, deduzco medidas concretas: mejores \u00edndices, estad\u00edsticas m\u00e1s actualizadas y formulaciones claras de las consultas. Con funciones JSON, extraigo fragmentos, identifico patrones y documento las decisiones de forma reproducible. De este modo, consigo que incluso las cargas de trabajo de SQL m\u00e1s extensas se ejecuten de forma fiable <strong>Actuaci\u00f3n<\/strong> y haz que las decisiones sobre el tuning sean comprensibles.<\/p>","protected":false},"excerpt":{"rendered":"<p>Aprende a utilizar el \u00abOptimizer Trace\u00bb de MariaDB para analizar y optimizar consultas SQL complejas. Este art\u00edculo explica c\u00f3mo activarlo, su estructura JSON y c\u00f3mo interpretar el \u00abOptimizer Trace\u00bb para mejorar el rendimiento.<\/p>","protected":false},"author":1,"featured_media":21324,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[781],"tags":[],"class_list":["post-21331","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-datenbanken-administration-anleitungen"],"acf":[],"_wp_attached_file":null,"_wp_attachment_metadata":null,"litespeed-optimize-size":null,"litespeed-optimize-set":null,"_elementor_source_image_hash":null,"_wp_attachment_image_alt":null,"stockpack_author_name":null,"stockpack_author_url":null,"stockpack_provider":null,"stockpack_image_url":null,"stockpack_license":null,"stockpack_license_url":null,"stockpack_modification":null,"color":null,"original_id":null,"original_url":null,"original_link":null,"unsplash_location":null,"unsplash_sponsor":null,"unsplash_exif":null,"unsplash_attachment_metadata":null,"_elementor_is_screenshot":null,"surfer_file_name":null,"surfer_file_original_url":null,"envato_tk_source_kit":null,"envato_tk_source_index":null,"envato_tk_manifest":null,"envato_tk_folder_name":null,"envato_tk_builder":null,"envato_elements_download_event":null,"_menu_item_type":null,"_menu_item_menu_item_parent":null,"_menu_item_object_id":null,"_menu_item_object":null,"_menu_item_target":null,"_menu_item_classes":null,"_menu_item_xfn":null,"_menu_item_url":null,"_trp_menu_languages":null,"rank_math_primary_category":null,"rank_math_title":null,"inline_featured_image":null,"_yoast_wpseo_primary_category":null,"rank_math_schema_blogposting":null,"rank_math_schema_videoobject":null,"_oembed_049c719bc4a9f89deaead66a7da9fddc":null,"_oembed_time_049c719bc4a9f89deaead66a7da9fddc":null,"_yoast_wpseo_focuskw":null,"_yoast_wpseo_linkdex":null,"_oembed_27e3473bf8bec795fbeb3a9d38489348":null,"_oembed_c3b0f6959478faf92a1f343d8f96b19e":null,"_trp_translated_slug_en_us":null,"_wp_desired_post_slug":null,"_yoast_wpseo_title":null,"tldname":null,"tldpreis":null,"tldrubrik":null,"tldpolicylink":null,"tldsize":null,"tldregistrierungsdauer":null,"tldtransfer":null,"tldwhoisprivacy":null,"tldregistrarchange":null,"tldregistrantchange":null,"tldwhoisupdate":null,"tldnameserverupdate":null,"tlddeletesofort":null,"tlddeleteexpire":null,"tldumlaute":null,"tldrestore":null,"tldsubcategory":null,"tldbildname":null,"tldbildurl":null,"tldclean":null,"tldcategory":null,"tldpolicy":null,"tldbesonderheiten":null,"tld_bedeutung":null,"_oembed_d167040d816d8f94c072940c8009f5f8":null,"_oembed_b0a0fa59ef14f8870da2c63f2027d064":null,"_oembed_4792fa4dfb2a8f09ab950a73b7f313ba":null,"_oembed_33ceb1fe54a8ab775d9410abf699878d":null,"_oembed_fd7014d14d919b45ec004937c0db9335":null,"_oembed_21a029d076783ec3e8042698c351bd7e":null,"_oembed_be5ea8a0c7b18e658f08cc571a909452":null,"_oembed_a9ca7a298b19f9b48ec5914e010294d2":null,"_oembed_f8db6b27d08a2bb1f920e7647808899a":null,"_oembed_168ebde5096e77d8a89326519af9e022":null,"_oembed_cdb76f1b345b42743edfe25481b6f98f":null,"_oembed_87b0613611ae54e86e8864265404b0a1":null,"_oembed_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_oembed_time_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_tldname":null,"_tldclean":null,"_tldpreis":null,"_tldcategory":null,"_tldsubcategory":null,"_tldpolicy":null,"_tldpolicylink":null,"_tldsize":null,"_tldregistrierungsdauer":null,"_tldtransfer":null,"_tldwhoisprivacy":null,"_tldregistrarchange":null,"_tldregistrantchange":null,"_tldwhoisupdate":null,"_tldnameserverupdate":null,"_tlddeletesofort":null,"_tlddeleteexpire":null,"_tldumlaute":null,"_tldrestore":null,"_tldbildname":null,"_tldbildurl":null,"_tld_bedeutung":null,"_tldbesonderheiten":null,"_oembed_ad96e4112edb9f8ffa35731d4098bc6b":null,"_oembed_8357e2b8a2575c74ed5978f262a10126":null,"_oembed_3d5fea5103dd0d22ec5d6a33eff7f863":null,"_eael_widget_elements":null,"_oembed_0d8a206f09633e3d62b95a15a4dd0487":null,"_oembed_time_0d8a206f09633e3d62b95a15a4dd0487":null,"_aioseo_description":null,"_eb_attr":null,"_eb_data_table":null,"_oembed_819a879e7da16dd629cfd15a97334c8a":null,"_oembed_time_819a879e7da16dd629cfd15a97334c8a":null,"_acf_changed":null,"_wpcode_auto_insert":null,"_edit_last":null,"_edit_lock":null,"_oembed_e7b913c6c84084ed9702cb4feb012ddd":null,"_oembed_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_time_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_03514b67990db061d7c4672de26dc514":null,"_oembed_time_03514b67990db061d7c4672de26dc514":null,"rank_math_news_sitemap_robots":null,"rank_math_robots":null,"_eael_post_view_count":"36","_trp_automatically_translated_slug_ru_ru":null,"_trp_automatically_translated_slug_et":null,"_trp_automatically_translated_slug_lv":null,"_trp_automatically_translated_slug_fr_fr":null,"_trp_automatically_translated_slug_en_us":null,"_wp_old_slug":null,"_trp_automatically_translated_slug_da_dk":null,"_trp_automatically_translated_slug_pl_pl":null,"_trp_automatically_translated_slug_es_es":null,"_trp_automatically_translated_slug_hu_hu":null,"_trp_automatically_translated_slug_fi":null,"_trp_automatically_translated_slug_ja":null,"_trp_automatically_translated_slug_lt_lt":null,"_elementor_edit_mode":null,"_elementor_template_type":null,"_elementor_version":null,"_elementor_pro_version":null,"_wp_page_template":null,"_elementor_page_settings":null,"_elementor_data":null,"_elementor_css":null,"_elementor_conditions":null,"_happyaddons_elements_cache":null,"_oembed_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_time_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_time_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_59808117857ddf57e478a31d79f76e4d":null,"_oembed_time_59808117857ddf57e478a31d79f76e4d":null,"_oembed_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_time_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_81002f7ee3604f645db4ebcfd1912acf":null,"_oembed_time_81002f7ee3604f645db4ebcfd1912acf":null,"_elementor_screenshot":null,"_oembed_7ea3429961cf98fa85da9747683af827":null,"_oembed_time_7ea3429961cf98fa85da9747683af827":null,"_elementor_controls_usage":null,"_elementor_page_assets":[],"_elementor_screenshot_failed":null,"theplus_transient_widgets":null,"_eael_custom_js":null,"_wp_old_date":null,"_trp_automatically_translated_slug_it_it":null,"_trp_automatically_translated_slug_pt_pt":null,"_trp_automatically_translated_slug_zh_cn":null,"_trp_automatically_translated_slug_nl_nl":null,"_trp_automatically_translated_slug_pt_br":null,"_trp_automatically_translated_slug_sv_se":null,"rank_math_analytic_object_id":null,"rank_math_internal_links_processed":"1","_trp_automatically_translated_slug_ro_ro":null,"_trp_automatically_translated_slug_sk_sk":null,"_trp_automatically_translated_slug_bg_bg":null,"_trp_automatically_translated_slug_sl_si":null,"litespeed_vpi_list":null,"litespeed_vpi_list_mobile":null,"rank_math_seo_score":null,"rank_math_contentai_score":null,"ilj_limitincominglinks":null,"ilj_maxincominglinks":null,"ilj_limitoutgoinglinks":null,"ilj_maxoutgoinglinks":null,"ilj_limitlinksperparagraph":null,"ilj_linksperparagraph":null,"ilj_blacklistdefinition":null,"ilj_linkdefinition":null,"_eb_reusable_block_ids":null,"rank_math_focus_keyword":"optimizer trace","rank_math_og_content_image":null,"_yoast_wpseo_metadesc":null,"_yoast_wpseo_content_score":null,"_yoast_wpseo_focuskeywords":null,"_yoast_wpseo_keywordsynonyms":null,"_yoast_wpseo_estimated-reading-time-minutes":null,"rank_math_description":null,"surfer_last_post_update":null,"surfer_last_post_update_direction":null,"surfer_keywords":null,"surfer_location":null,"surfer_draft_id":null,"surfer_permalink_hash":null,"surfer_scrape_ready":null,"_thumbnail_id":"21324","footnotes":null,"_links":{"self":[{"href":"https:\/\/webhosting.de\/es\/wp-json\/wp\/v2\/posts\/21331","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webhosting.de\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webhosting.de\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webhosting.de\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/webhosting.de\/es\/wp-json\/wp\/v2\/comments?post=21331"}],"version-history":[{"count":0,"href":"https:\/\/webhosting.de\/es\/wp-json\/wp\/v2\/posts\/21331\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/webhosting.de\/es\/wp-json\/wp\/v2\/media\/21324"}],"wp:attachment":[{"href":"https:\/\/webhosting.de\/es\/wp-json\/wp\/v2\/media?parent=21331"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webhosting.de\/es\/wp-json\/wp\/v2\/categories?post=21331"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webhosting.de\/es\/wp-json\/wp\/v2\/tags?post=21331"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}