20-Aug-15 SQL Server Query Processor Ing. Eduardo Castro, PhD Microsoft SQL Server MVP PASS Regional Mentor PASS Global Board of Directors Advisor [email protected] http://www.youtube.com/eduardocastrom Patrocinadores del SQL Saturday Gold Sponsor Bronze Sponsor Geek Sponsor 1 20-Aug-15 Referencias Understanding QP. C F. Software Design Engineer. Microsoft SQL Server Agenda • • • • SQL Server engine architecture Query execution Showplan Iteradores de SQL 2 20-Aug-15 SQL Server Engine Arquitectura de Alto Nivel Metadata, Type System, Expression Services Query Optimization Query Execution (Plan Generation, View Matching, Statistics, Costing) (Query Operators, Memory Grants, Parallelism, Showplan) Storage Engine (Access Methods, Buffer Pool, Locking, Transactions, …) SQL-OS (Threads, Memory Management, Synchronization, …) Utilities (DBCC, Backup/Restore, BCP, …) LanguageProcessing (Parse/Bind, Statement/Batch Execution, Plan Cache) Introducción al Query Optimizer En el núcleo del motor de base de datos de SQL Server hay dos componentes principales: el motor de almacenamiento motor y el procesador de consultas, también llamado el motor relacional. El motor de almacenamiento es responsable de la lectura de datos entre el disco y la memoria de manera que se optimice concurrencia mientras mantiene la integridad de los datos. El procesador de consultas, como sugiere el nombre, acepta todas las consultas a SQL Server, idea un plan para su óptima ejecución, y luego ejecuta el plan y ofrece los resultados requeridos. Inside the SQL Server Query Optimizer. Benjamin Nevarez. 3 20-Aug-15 Introducción al Query Optimizer Para cada query que recibe, el trabajo del procesador de consultas es idear un plan, tan pronto como sea posible, que describa la mejor manera posible (o, al menos, una forma eficiente) de ejecutar dicha consulta. Su segundo trabajo es ejecutar la consulta de acuerdo con ese plan. Cada una de estas tareas se delega en un componente separado dentro del procesador de consultas; el optimizador de consultas diseña el plan y luego lo pasa al motor de ejecución, que realmente ejecutar el plan y obtiene los resultados de la base de datos. Inside the SQL Server Query Optimizer. Benjamin Nevarez. Libro De Referencia 4 20-Aug-15 El procesamiento de consultas Parsing and binding - La consulta es parsed and bound. Asumiendo que la consulta es válida, la salida de esta fase es un árbol lógico Con cada nodo en el árbol representa una operación lógica que la consulta debe llevar a cabo, como la lectura de una tabla en particular hacer un inner join. Un planes de ejecución es, en esencia, un conjunto de operaciones físicas por ejemplo, Index Seek, a Nested Loops Join que se pueden realizar para producir el resultado deseado, tal como se describe por el árbol lógico Inside the SQL Server Query Optimizer. Benjamin Nevarez. El procesamiento de consultas Optimización de consultas - El árbol lógico se usa entonces para ejecutar la optimización de la consulta, que a grandes rasgos se compone de los siguientes dos pasos: Generación de posibles planes de ejecución - Utilizando el árbol lógico, el optimizador elabora una serie de posibles formas de ejecutar la consulta, es decir, un número de posibles planes de ejecución Evaluación de costo de cada plan - Mientras que el optimizador de consultas no genera cada posible plan de ejecución, sí evalúa el costo de los recursos y el tiempo de cada plan; el plan que el optimizador de consultas considera que tiene el menor costo es seleccionado, y lo pasa al motor de ejecución. Inside the SQL Server Query Optimizer. Benjamin Nevarez. 5 20-Aug-15 El procesamiento de consultas Query execution, plan caching - la consulta es ejecutada por el motor de ejecución, según el plan seleccionado; el plan puede ser almacenado en la memoria caché. Inside the SQL Server Query Optimizer. Benjamin Nevarez. El proceso de optimización El proceso de optimización, es la generación de los planes de ejecución candidatos y la selección de los mejores de estos planes de acuerdo a su costo. El optimizador de consultas de SQL Server utiliza un modelo de estimación de costos para estimar el costo de cada uno de los planes de candidatos. Inside the SQL Server Query Optimizer. Benjamin Nevarez. 6 20-Aug-15 El proceso de optimización La optimización de consultas es el proceso e mapear las operaciones lógicas del árbol original en su equivalente de operaciones físicas, las cuales serán ejecutadas por el motor de ejecución. La funcionalidad del motor de ejecución aplicar los planes de ejecución que son creados por el optimizador de consultas. El motor de ejecución implementa cierto número de diferentes algoritmos, y a partir de estos algoritmos que el optimizador de consultas debe elegir, cómo formula los planes de ejecución. Inside the SQL Server Query Optimizer. Benjamin Nevarez. El proceso de optimización Se traducen las operaciones lógicas originales en el operaciones físicas que el motor de ejecución es capaz de realizar, y los planes de ejecución incluyen tanto las operaciones lógicas y físicas. Algunos operaciones lógicas, como un Sort se traducen a la misma operación física, mientras que otras operaciones lógicas se traducen a varias operaciones físicas. Por ejemplo, una join lógico se puede traducir en un Nested Loops Join, Merge Join, o Hash Join . Inside the SQL Server Query Optimizer. Benjamin Nevarez. 7 20-Aug-15 El proceso de optimización El producto final del proceso de optimización de la consulta es un plan de ejecución: un árbol que consiste de un número de operadores físicos, que contienen los algoritmos que serán ejecutados por el motor de ejecución con el fin de obtener los resultados deseados desde la base de datos. Inside the SQL Server Query Optimizer. Benjamin Nevarez. Generación de planes de ejecución candidatos El propósito básico del optimizador de consultas es encontrar un plan de ejecución eficiente para su búsqueda. Incluso para las consultas relativamente simples, puede haber un gran número de diferentes caminos acceder a los datos para producir el mismo resultado final. El Optimizador de Consultas tiene que seleccionar el mejor plan posible de un gran número planes candidatos, y es importante que haga una buena elección, ya que el tiempo necesario para volver los resultados al usuario pueden variar mucho, dependiendo de qué plan es seleccionado. Inside the SQL Server Query Optimizer. Benjamin Nevarez. 8 20-Aug-15 Generación de planes de ejecución candidatos El optimizador de consultas debe lograr un equilibrio entre el tiempo de optimización y calidad del plan. Por ejemplo, si el optimizador de consultas gasta un segundo hallazgo un buen lo suficientemente plan de que ejecuta en un minuto, entonces no tiene sentido tratar de encontrar el plan perfecto o más plan óptimo, si esto va a tomar cinco minutos de tiempo de optimización, más el tiempo de ejecución. Así que SQL Server no realiza una búsqueda exhaustiva, sino que intenta encontrar un plan eficiente tan rápidamente como sea posible. Inside the SQL Server Query Optimizer. Benjamin Nevarez. Generación de planes de ejecución candidatos Con el fin de explorar el espacio de búsqueda, el optimizador de consultas utiliza reglas de transformación y heurística. Los generación de planes de ejecución de candidatos se realiza dentro del optimizador de consultas usando reglas de transformación, y con el uso de heurísticas limita el número de opciones, con el fin de mantener el tiempo de optimización razonable. Los planes candidatos son almacenado en la memoria durante la optimización, en un componente llamado Memo. Inside the SQL Server Query Optimizer. Benjamin Nevarez. 9 20-Aug-15 El procesamiento de consultas Inside the SQL Server Query Optimizer. Benjamin Nevarez. Cómo funciona el procesamiento de consultas New Statement Found Executable Plan Plan Cache Found Compiled Plan LanguageProcessing (Parse/Bind, Statement/Batch Execution, Plan Cache) Not Found Parse Auto-Param Query Optimization Query Execution (Plan Generation, View Matching,Statistics, Costing) (Query Operators, Memory Grants, Parallelism, Showplan) Bind, Expand Views Query Optimization Generate Executable Plan Fix Memory Grant & DoP Execute Return Plans to Cache 10 20-Aug-15 Flujo de ejecución de Queries • • • • Query plans son árboles de iteración Iterador = unidad básica del query plan execution Cada iterador tiene 0, 1, 2, o N hijos Los métodos principales de cada iterador son: – Open – GetRow – Close • Los flujos de control van hacia abajo en el árbol • Data flows (se llenan) hacia arriba en el árbol Consulta de ejemplo Obtenga toda la información acerca line-items que están filtrados por proveedores y partes SELECT l_orderkey, l_linenumber, o_orderstatus FROM lineitem JOIN orders ON l_orderkey = o_orderkey WHERE l_suppkey < 2000 AND l_partkey < 2000 l_orderkey, l_linenumber, o_orderstatus l_suppkey<2000, l_partkey<2000 l_orderkey=o_orderkey lineitem orders 11 20-Aug-15 SQL Server Query Optimizer Basado en el Cascades Framework Basado en transformación, enfoque top-down Optimization = Tasks + Memo ( Programs = Algorithms + Data Structures ) Completamente basado en costos Flexible y con extensiones Se pueden agregar nuevos operadores y reglas SQL Query Normalization (predicate unfolding, join collapsing, view substitution, etc.) Parsing, Validation Cost-based Optimization Execution Plan The Memo Search Space Memory Compactly stores all explored alternatives (AND-OR graph) Groups together equivalent operator trees and their plans Provides memoization, duplicate detection, property and cost management, etc. Groups a<10 R b>20 S b>20 a<10 1) SELECT (a<10, ) R R Expressions 1) SELECT (a<10, ) 2) JOIN (x=y, , ) 3) ... 1) GET(R) R b>20 1) SELECT (b>20, ) S S S 1) JOIN (x=y, , ) 2) ... 1) GET(S) 12 20-Aug-15 Optimization Tasks Optimize Inputs Obtain optimization context Optimize children groups Calculate costs, pick best Initialize Memo Optimize Root Group Optimize Group Apply Rule Explore Group Obtain enforcers and implementation rules for all expressions Apply Rules by Promise Pruning checks Generate bindings, substitutes Restrict ruleset optimizing?Opt Inputs:Explore Explore Expression Explore Group Apply-always rules Explore Inputs Rest of Apply-always Rules Other Rules by Promise For each expression -Get Guidance -Explore Expression. Planteamiento del Problema Workload Database Physical Design Tool Configuration Conjunto de estructuras físicas (es decir, índices y vistas) que hacen que las cargas de trabajo similares ejecutar lo más rápido posible 13 20-Aug-15 Database Tuning Advisor Yukon Carga de trabajo Comprimir la carga de trabajo Selección de candidatos (Por consulta) La fusión Sintonización Cliente Optimizador de consultas Y si API Base de datos Servidor Metadatos ... Enumeración Sí - Crear hipotético Índice / Vista. - Optimizar consultas con respecto a las configuraciones hipotéticas. Tiempo? No Recomendación Nueva Arquitectura Workload Get Optimal Configuration (per query) Tuning Client Relaxation Yes Time? No Requests API Request Identification What-if API Query Optimizer Database Server Metadata … Recommendation Instrumentación el optimizador de consultas. Estrategia de búsqueda basado en relaxations. 14 20-Aug-15 Tipos de iteradores • • • • • • Scan and seek Joins Aggregates Sorts Spools Parallelism • • • • • • Insert, update, and delete Top Compute scalar Filter Concatenation Sequence Showplan • Muestra el plan de ejecución • Excelente herramienta ... – Para entender qué es lo que está haciendo SQL Server – Para diagnosticar problemas de desempeño • Un montón de Estadísticas ... – Cantidad Estimada y real de fila • Gráfica, texto, y XML versiones – XML desde SQL Servidor 2005 15 20-Aug-15 Gráfico vs XML Gráfico Vista con base en íconos Da una vista general Fácil identificar los iteradores más costosos Provee ayuda para cada iterador XML Vista gráfica sencilla desde SQL Server 2005 Muestra mayor detalle Más difícil de leer que los planes gráficos | --Stream Agregado | --sort | --Nested Loops | Índice --Clustered Buscar | --index Verk ... <RelOp NodeID= "0" ...> <StreamAggregate> <RelOp NodeID= "1" ...> <Ordenar ...> ... Leyendo planes • Gráfico – Cada icono representa un iterador en el árbol – Estructura del árbol estructura y flujos de datos están representados por flechas que conectan los iconos – Más información es disponible en el información sobre herramientas y en el "propiedades" cristal • XML – Un elemento por iterador más los elementos adicionales para otra información – Estructura del árbol es representado por anidamiento de elementos – Flujos de datos están en los elementos más exteriores 16 20-Aug-15 Showplan ejemplos DECLARE @Date DATETIME SET @Date = '1996-07-04' SELECT L_SHIPDATE, COUNT_BIG(*) FROM LINEITEM JOIN ORDERS ON L_ORDERKEY = O_ORDERKEY WHERE O_ORDERDATE = @Date GROUP BY L_SHIPDATE ORDER BY L_SHIPDATE Plan de ejemplo 17 20-Aug-15 Plan de ejemplo Plan ejemplo |--Stream Aggregate(GROUP BY:([L_SHIPDATE]) DEFINE:([Expr1008]=Count(*))) |--Sort(ORDER BY:([L_SHIPDATE] ASC)) |--Nested Loops(Inner Join, OUTER REFERENCES:(*ORDERS+.*O_ORDERKEY+, …) …) |--Clustered Index Seek(OBJECT:(*ORDERS+.*O_ORDERDATE_CLUIDX+), SEEK:(*O_ORDERDATE+=*@Date+) …) |--Index Seek(OBJECT:(*LINEITEM+.*L_ORDERKEY_IDX+), SEEK:(*L_ORDERKEY+=*O_ORDERKEY+)…) 18 20-Aug-15 XML Plan <ShowPlanXML xmlns="http://schemas.microsoft.com/…" Version="1.0" Build="10.0.…"> <BatchSequence> <Batch> <Statements> <StmtSimple StatementText="SELECT …" StatementId="1" StatementCompId="2" …> <StatementSetOptions QUOTED_IDENTIFIER="false" ARITHABORT="true" … /> <QueryPlan DegreeOfParallelism="1" MemoryGrant="1392" …> <RelOp …> … </RelOp> <ParameterList> <ColumnReference Column="@Date" ParameterCompiledValue="'1996-03-15 …'" ParameterRuntimeValue="'1996-07-04 …'" </ParameterList> /> </QueryPlan> </StmtSimple> </Statements> </Batch> </BatchSequence> </ShowPlanXML> XML Plan <RelOp <ShowPlanXML NodeId="0" xmlns="http://schemas.microsoft.com/…" PhysicalOp="Stream Aggregate" LogicalOp="Aggregate" Version="1.0" Build="10.0.…"> …> <StreamAggregate> <BatchSequence> <RelOp <Batch>NodeId="1" PhysicalOp="Sort" LogicalOp="Sort" …> <Statements> <MemoryFractions Input="0.782609" Output="1" /> <Sort <StmtSimple Distinct="0"> StatementText="SELECT …" StatementId="1" StatementCompId="2" …> <RelOp <StatementSetOptions NodeId="2" PhysicalOp="Nested QUOTED_IDENTIFIER="false" Loops" LogicalOp="Inner ARITHABORT="true" Join" … …> /> <QueryPlan DegreeOfParallelism="1" MemoryGrant="1392" …> <NestedLoops Optimized="1" WithUnorderedPrefetch="1"> <RelOp …> NodeId="5" PhysicalOp="Clustered Index Seek" …> … <IndexScan Ordered="1" ScanDirection="FORWARD" …> </RelOp> <Object … Table="[ORDERS]" Index="[O_ORDERDATE_CLUIDX]" … /> <ParameterList> </IndexScan> <ColumnReference Column="@Date" </RelOp> <RelOp NodeId="6" PhysicalOp="Index ParameterCompiledValue="'1996-03-15 Seek" …> …'" <IndexScan Ordered="1" ParameterRuntimeValue="'1996-07-04 ScanDirection="FORWARD" …> …'" /> </ParameterList> <Object … Table="[LINEITEM]" Index="[L_ORDERKEY_IDX]" … /> </QueryPlan> </IndexScan> </StmtSimple> </RelOp> </Statements> </NestedLoops> </Batch> </RelOp> </BatchSequence> </Sort> </ShowPlanXML> </RelOp> </StreamAggregate> </RelOp> 19 20-Aug-15 XML Plan <ShowPlanXML xmlns="http://schemas.microsoft.com/…" Version="1.0" Build="10.0.…"> <RelOp NodeId="5" <BatchSequence> PhysicalOp="Clustered Index Seek" LogicalOp="Clustered Index Seek" <Batch> EstimateRows="623.462" …> <OutputList> <Statements> <ColumnReference <StmtSimple StatementText="SELECT … Table="[ORDERS]" Column="O_ORDERKEY" …" StatementId="1"/>StatementCompId="2" …> </OutputList> <StatementSetOptions QUOTED_IDENTIFIER="false" ARITHABORT="true" … /> <RunTimeInformation> <QueryPlan DegreeOfParallelism="1" MemoryGrant="1392" …> <RelOp …> … <RunTimeCountersPerThread Thread="0" ActualRows="629" … ActualExecutions="1" /> </RelOp> </RunTimeInformation> <ParameterList> <IndexScan Ordered="1" ScanDirection="FORWARD" ForcedIndex="0" <ColumnReference Column="@Date" ForceSeek="0" NoExpandHint="0"> ParameterCompiledValue="'1996-03-15 …'" <DefinedValues> ParameterRuntimeValue="'1996-07-04 …'" /> <DefinedValue> </ParameterList> <ColumnReference … Table="[ORDERS]" Column="O_ORDERKEY" /> </QueryPlan> </DefinedValue> </StmtSimple> </DefinedValues> </Statements> <Object … Table="[ORDERS]" Index="[O_ORDERDATE_CLUIDX]" IndexKind="Clustered" /> </Batch> <SeekPredicates> </BatchSequence> … </ShowPlanXML> </SeekPredicates> </IndexScan> </RelOp> XML plan Text plan Text/XML plan options Command Execute Display Query? Estimated Row Counts & Stats Display Actual Row Counts SET SHOWPLAN_TEXT ON SET SHOWPLAN_ALL ON SET STATISTICS PROFILE ON SET SHOWPLAN_XML ON SET STATISTICS XML ON No No No No Yes No Yes Yes Yes No Yes No Yes Yes Yes SQL Profiler y DMVs también muestran los planes 20 20-Aug-15 Iteradores comunes • Scans and seeks • Join iterators – Nested loops join – Merge join – Hash join • Aggregation iterators – Stream aggregrate – Hash aggregate • Los iteradores no son buenos ni males • No existe “el mejor” join o tipo de agregación • Cada iterador funciona bien dependiendo del escenario Scans and seeks • Scans devuelve toda una tabla o un índice – Los scan de índices pueden ser con o sin orden • Seeks devuelve de forma eficiente las filas de uno o más rangos de un índice – Los seeks de un índice siempre son ordenados 21 20-Aug-15 Index scan vs. index seek Select Price from Orders where OrderKey = 2 1 86.00 2 17.00 3 88.00 … … 2 17.00 Index Scan Where OrderKey = 2 Index Seek Where OrderKey = 2 OrderKey Price 1 86.00 2 17.00 3 88.00 4 17.00 5 96.00 6 22.00 7 74.00 8 94.00 9 56.00 … … Nested loops join • Algoritmo básico: 1. 2. 3. Obtener una fila de la entrada izquierda Obtener todas filas de la entrada derecha que corresponde a la fila de la entrada izquierda Cuando ya no hay más filas que hagan match desde la entrada derecha, obtenga la siguiente fila de la entrada izquierda y repita • Parámetros correlacionados – Datos de la entrada izquierda afecta los datos devuelto por la entrada derecha (es decir, paso 2 depende de paso 1) – Si no se tienen parámetros correlacionados cada ejecución de la entrada derecha se produce el mismo resultado 22 20-Aug-15 Nested loops join example Select C.Name, O.Price from Cust C join Orders O on O.CustKey = C.CustKey where C.City = ‘Boston’ Alice 88.00 Bob 86.00 Bob 94.00 Bob 56.00 Nested Loop Join 4 Boston Alice 5 Boston Bob 6 Boston Cathy 4 Index Seek Cust Index Seek Orders Where C.City = ‘Boston’ On O.CustKey = C.CustKey 88.00 5 86.00 5 94.00 5 56.00 No rows match CustKey = 6 Nested loops join • El único tipo join... • • La entrada derecha puede ser un index seek o un subplan complejo Optimizaciones: • Tips de desempeño: – Que soporta predicados de inequidad – Usar índices para optimizar la selección de filas que hacen match de la entrada derecha filas (Además conocido como una índice unirse a) – Usar lazy spool en la entrada derecha si esperamos duplicar filas de la entrada izquierda – Costo es proporcional a la producto de la cardinalidad de las entradas izquierda y derecha – En general es mejor para conjuntos de datos pequeños – Crear un índice para cambiar el producto cartersiano en un index join – Verifique si se da gran cantidad de I/Os aleatorios 23 20-Aug-15 Columnas indizadas • Key columns: – Conjunto de columnas que puede ser utilizado en un índice – En un índice compuesto, el orden del columnas importa: • Determina el ordenamiento del índice • Solo puede hacer seek en una columna si todas las columnas anteriores tienen predicados de equidad – Los non-unique non-clustered index en una tabla con un clustered index incluye implícitamente el clustered index para las llaves • Covered columns: – Conjunto de columnas que pueden ser la salida de un seek o scan del índice – Heap Index o Clustered Index siempre cubren todas las columnas – Non-clustered index cubre las columnas llave del índice y si la tabla tiene clustered index las llaves del clustered index – Se pueden agregar más columnas durante la creación del índice Bookmark lookup • Pregunta: – Lo que pasa si el non-clustered index para un seek no cubre todas de la columnas necesarias por la consulta? • Respuesta: – Look up las columnas extra en el heap o clustered index – Esta operación es conocida como bookmark lookup • SQL Server 2000 tenía bookmark lookup iterator • SQL Server 2005 y 2008 no tienen un bookmark lookup iterator – En su lugar simplemente unen el non-clustered index con el clustered index usando un nested loops join – Para saber si se usa un bookmark lookup, busque el keyword “LOOKUP” en el clustered index seek – Bookmark lookup provoca I/Os aleatorios: afecta el desempeño 24 20-Aug-15 Bookmark lookup example OrderKey CustKey Price 1 5 86.00 2 2 17.00 3 4 88.00 4 9 17.00 5 1 96.00 6 7 22.00 7 8 74.00 Clustered Index Seek 8 5 94.00 9 5 56.00 Select Price … … … Select Price from Orders where CustKey = 5 1 5 86.00 8 5 94.00 9 5 56.00 1 5 8 5 9 5 Nested Loop Join Index Seek Where CustKey = 5 Clustered index on OrderKey Non-clustered index on Custkey Merge Join • Requiere al menos un predicado equijoin • Datos debe estar ordenados en los join keys – Sort Order debe ser proporcionado por un índice – O puede incluir un sort explícito • Algoritmo Básico : 1. Obtener una fila de las entradas izquierda y derecha 2. Si las filas coinciden devuelva la fila unida 3. De lo contrario, obtenga una nueva fila de cualquier entrada que sea la más pequeña y repita 25 20-Aug-15 Merge join Select C.Name, O.Price from Cust C join Orders O on O.CustKey = C.CustKey where C.City = ‘Boston’ Alice 88.00 Bob 86.00 Bob 94.00 Bob 56.00 Merge Join O.CustKey = C.CustKey 2 4 Boston Alice 5 Boston Bob 6 Boston Cathy Index Seek Cust Index Scan Orders Where C.City = ‘Boston’ 17.00 4 88.00 5 86.00 5 94.00 5 56.00 7 22.00 Cust and Orders indexes ordered by CustKey Merge join • Optimizaciones: – One to many join – Inner join terminates tan pronto como una de las entradas se termina • Tips de desempeño: – Costo es proporcional a la suma de las cardinalidades de las entradas – Tiene buen desempeño para entradas grandes y pequeñas especialmente si el sort order es proveído por un índice – Si el merge join plan incluye sort explícitos, vigile que no se den splilling – No funciona tan bien en paralelo como un hash join 26 20-Aug-15 Hash join • Requiere al menos un predicado equijoin • Algoritmo Básico : 1. Obtener todas filas de la entrada izquierda 2. Construir un in-memory hash table utilizando filas de la entrada izquierda 3. Obtener todas las filas de la entrada derecha 4. Utilizar el hash table para encontrar coincidencias • Requiere memoria para construir el hash table • Si el join se queda sin memoria, porciones las entradas izquierdas y derechas deben ser enviadas a disco y manejadas en pasadas distintas Bob Select C.Name, O.Price from Cust C join Orders O on O.CustKey = C.CustKey where C.City = ‘Boston’ 86.00 Alice 88.00 Bob 94.00 Bob 56.00 Hash join example Hash Table Hash Join 5 Boston Bob 4 Boston Alice 6 Boston Cathy Index Seek Cust O.CustKey = C.CustKey 5 Table Scan 2 Orders Where C.City = ‘Boston’ 86.00 17.00 4 88.00 9 17.00 5 94.00 5 56.00 Order of Cust and Orders tables does not matter 27 20-Aug-15 Hash join • Fuciona como stop and go en la entrada izquierda • Optimizaciones: – Construir la tabla hash la entrada más pequeña – Si el join hace splills, puede hacer switch de las entradas – Puede utilizar bitmap para descartar entradas de la fila de derecha más rápido • Tips de desempeño: – – – – Costo es proporcional a la suma de las cardinalidades de las entradas Generalmente se desempeña bien para conjuntos de datos grandes Los parallel hash joins escalan bien Verifique no se dén spilling, especialmente múltiples pasadas (utilice el SQL Profiler) Stream aggregate • Los datos deben estar ordenados en grupos por la llave • El ordenamiento agrupa las filas con llaves iguales juntas • Procesa los grupos de uno en uno • No causa bloqueos o utiliza memoria • Es eficiente si el sort order es proveído por un índice o sí el plan incluye ordamientos • Es la opción para scalar aggregates 28 20-Aug-15 Stream aggregate example Select CustKey, sum(Price) from Orders group by CustKey 4 88.00 5 236.00 7 22.00 Stream Agg 4 88.00 5 86.00 5 94.00 5 56.00 7 22.00 Index Scan Orders index ordered by CustKey Hash aggregate • • • • Datos no tiene que estar ordenados Construye una tabla hash para todos los grupos Stop and go Al igual que un hash join : – Requiere memoria, puede utilizar disco si se acaba la memoria – Generalmente mejor para conjuntos de datos grandes – Los Parallel hash aggregates escalan bien • Valores con llaves duplicadas... – Puede ser malo para un hash join porque no es posible subdividir un hash bucket que tiene todos duplicados – Son buenos para un hash aggregate debido a que los duplicados colapsan dentro una única entrada de la tabla hash 29 20-Aug-15 Hash aggregate example Select CustKey, sum(Price) from Orders group by CustKey Hash Table 7 22.00 4 88.00 5 236.00 Hash Agg 5 86.00 4 88.00 7 22.00 5 94.00 5 56.00 Table Scan Order of Orders table does not matter Tips de desempeño • Vigile errores en los cardinality estimates – – – • Recomendaciones generales: – – – – – – • Utilice set based queries Evite joining columns con mismatched data types Evite outer joins, cross applies, complex sub-queries, dynamic index seeks, … Evite dynamic SQL Utilice SET STATISTICS IO ON para vigilar si de dan mucha cantidad de I/Os Utilice índices como workaround locking, concurrency, and deadlock issues OLTP: – – • Los errores se propagan hacia arriba, debe buscar la raíz de la causa Asegúrese que las estadísticas están actualizadas y que son lo más exactas posible Evite el uso excesivo de predicatos complejos Evite iterados que consuman memoria o que causen bloqueos Utilice seeks no scans DW : – – Utilice planes paralelos Verifique que no se den skews in los planes paralelos 30 20-Aug-15 Otros planes de ejecución • Static vs. dynamic index seeks • Insert, update, y delete plans – Update por row vs. por index – Split sort collapse updates Static vs. dynamic index seeks • Static index seeks – Los rangos son conocidos y no se traslapan en tiempo de compilación – Standalone index seek iterator • Dynamic index seeks – Los rangos se traslapan en tipo de de ejecución – Típicamente se utilzian con predicados OR’ed con T-SQL o parámetros correlacionados: • … where State = @p1 or State = @p2 – Sort and merge (merge interval iterator) los rangos cambian en tiempo de ejecución según sea necesario 31 20-Aug-15 Dynamic index seek plan Merge interval Select * from T where [C] between @p1 and @p2 or [C] between @p3 and @p4 or [C] between @p5 and @p6 @p1 @p2 @p3 @p5 @p4 @p6 We must not scan this range twice! 32 20-Aug-15 Merge interval Select * from T where [C] between @p1 and @p2 or [C] between @p3 and @p4 or [C] between @p5 and @p6 @p1 Sort @p2 @p5 @p6 @p3 @p4 We must not scan this range twice! Merge interval Select * from T where [C] between @p1 and @p2 or [C] between @p3 and @p4 or [C] between @p5 and @p6 Merge @p1 @p6 @p3 @p4 Each unique range scanned only once! 33 20-Aug-15 Insert, update, and delete plans • Todos los planes de update tienen dos partes: – Read cursor devuelve las filas para insert, update, or delete – Write cursor • Ejecuta el insert, update, o delete • Mantiene los non-clustered indexes • También los checks constraints, indexed views, … • La mayoría de las veces es un único update iterator Per row vs. per index updates • Per row plans: – Un único update iterator mantiene todos los índices (lo cual incluye heap o clustered index y todos los non-clustered indexes) – Lee una fila de la entrada a la vez y después modifica todos los índices afectados • Per index plans: – El plan tiene un iterador de update separado para cada índice afectado – Cada iterador de update mantiene sólo un índice – Lee y pone en spool todas las filas de entrada antes de modificar cualquier índice – Aplica todas las modificaciones en un índice a la vez • Por qué per index? – Para desempeño en large updates (e.g., sort on index key) 34 20-Aug-15 Per row update plan Write cursor Read cursor Per row update plan Write curs or Read cursor 35 20-Aug-15 Per index update plan Read cursor Write cursor Split sort collapse updates Update T set UniqCol = UniqCol + 1 • Debe asegurarse que los update a los unique indexes no hacen violaciones de unicidad • Los iteradores de split, sort, y collapse iterators reorganizan el flujos de filas a actualizar para garantizar que no existe violaciones de unicidad 36 20-Aug-15 Split sort collapse Update T set UniqCol = UniqCol + 1 Old Collapse Del 1 X Del 2 Y Ins 2 X Ins 3 Y New 1 2 X 2 3 Y 1 X Upd 2 Y Ins 3 Del 1 X Ins 2 X Del 2 Y Ins 3 Y Data 1 X 2 Y X Y Sort Split Old Del New UniqCol SQL Server 2016 Query Store Regresiones de planes Identificar a los grandes consumidores Evitar riesgos de upgrades de SQL Server Analizar cargas de trabajo 37 20-Aug-15 Resumen • • Los iteradores son los bloques básicos del query execution y query plans Showplan – Graphical – Text – XML • • Scan vs. seek vs. bookmark lookup Existen tres join iterators: – Nested loops join – Merge join – Hash join • Dos aggregation iterators: – Stream aggregate – Hash aggregate Referencias • Libros… – Inside SQL Server 2005: Query Tuning and Optimization • Blogs … – http://blogs.msdn.com/craigfr – http://blogs.msdn.com/sqlqueryprocessing • Otras fuentes… – – – – Books online MSDN Newsgroups and forums Web search 38 20-Aug-15 Evaluaciones Evaluacion del evento http://www.sqlsaturday.com/443/eventeval.aspx Evaluacion de las charlas http://www.sqlsaturday.com/443/sessions/sessionevaluation.aspx PREGUNTAS Y RESPUESTAS [email protected] http://ecastrom.blogspot.com Eduardo Castro edocastro 78 | 39