{"id":1475,"date":"2018-10-24T15:30:45","date_gmt":"2018-10-24T15:30:45","guid":{"rendered":"https:\/\/www.tiagoneves.net\/blog\/?p=1475"},"modified":"2018-10-24T15:30:45","modified_gmt":"2018-10-24T15:30:45","slug":"voce-sabe-a-diferenca-entre-uma-consulta-sargable-e-non-sargable","status":"publish","type":"post","link":"https:\/\/www.tiagoneves.net\/blog\/voce-sabe-a-diferenca-entre-uma-consulta-sargable-e-non-sargable\/","title":{"rendered":"Voc\u00ea sabe a diferen\u00e7a entre uma consulta Sargable e Non-Sargable?"},"content":{"rendered":"<p>Ol\u00e1 pessoal tudo certo?<\/p>\n<p>No post de hoje vou compartilhar com voc\u00eas a respeito de um conceito muito comum no SQL Server, que \u00e9 o conceito de SARG (&#8220;<strong>S<\/strong>&#8220;<em> search argument<\/em>) e Non-SARGable cuja a tradu\u00e7\u00e3o livre pode ser &#8220;<strong>Argumento de busca<\/strong>&#8220;.<\/p>\n<p>O termo <strong>SARG<\/strong> nada mais \u00e9 que a coluna que voc\u00ea est\u00e1 utilizando como &#8220;<strong>predicate<\/strong>&#8221; na cl\u00e1usula <strong>WHERE<\/strong> se ela pode ser utilizada em uma opera\u00e7\u00e3o de &#8220;<strong>Index Seek<\/strong>&#8220;. J\u00e1 quando o nosso &#8220;predicate&#8221; <strong>N\u00c3O<\/strong> permite a opera\u00e7\u00e3o de &#8220;Index Seek&#8221;, podemos dizer que estamos utilizando um &#8220;<em>predicate Non-Sargable<\/em>&#8221; e consequentemente teremos um <strong>custo maior<\/strong> para execu\u00e7\u00e3o da query.<\/p>\n<p>Vamos observar na pr\u00e1tica como isso funciona. Eu utilizei os scripts abaixo no banco <strong>AdventureWorks<\/strong>.<\/p>\n<pre class=\"theme:ssms2012 lang:tsql decode:true\">--Vamos retornar todos os funcion\u00e1rios com o nome \"Paul\"\r\n\r\nSELECT B.FirstName,B.LastName,A.BirthDate\r\nFROM HumanResources.Employee A\r\nJOIN Person.Person B ON B.BusinessEntityID = A.BusinessEntityID\r\nWHERE B.FirstName = 'Paul'\r\n\r\n--Custo de execu\u00e7\u00e3o\r\nTable 'Employee'. Scan count 0, logical reads 18\r\nTable 'Person'. Scan count 1, logical reads 117\r\nSQL Server Execution Times:\r\n   CPU time = 0 ms,  elapsed time = 36 ms.<\/pre>\n<p>Observando o plano de execu\u00e7\u00e3o, podemos ver que o pr\u00f3prio SQL, nos sugere a cria\u00e7\u00e3o de um \u00edndice na coluna <strong>FirstName<\/strong>.<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_1.png?ssl=1\" rel=\"lightbox[1475]\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1478\" src=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_1.png?resize=678%2C109&#038;ssl=1\" alt=\"\" width=\"678\" height=\"109\" srcset=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_1.png?w=1388&amp;ssl=1 1388w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_1.png?resize=300%2C48&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_1.png?resize=768%2C124&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_1.png?resize=1024%2C165&amp;ssl=1 1024w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/a><\/p>\n<p>Ent\u00e3o vamos criar o \u00edndice para ver como que a consulta vai ficar.<\/p>\n<pre class=\"theme:ssms2012 lang:tsql decode:true\">CREATE INDEX IX_Person ON Person.Person\r\n(FirstName)\r\nWITH(FILLFACTOR=90)\r\n\r\n--Custo de execu\u00e7\u00e3o\r\nTable 'Person'. Scan count 1, logical reads 11\r\nTable 'Employee'. Scan count 1, logical reads 9\r\n\r\n SQL Server Execution Times:\r\n   CPU time = 0 ms,  elapsed time = 32 ms.<\/pre>\n<p>Como podemos ver o custo da execu\u00e7\u00e3o reduziu para 32 milissegundos, enquanto o numero de leituras na tabela &#8220;<strong>Person.Person<\/strong>&#8221; reduziu de 117 para apenas 9 reads. Podemos observar tamb\u00e9m que no plano de execu\u00e7\u00e3o o SQL deixou de fazer um &#8220;<strong>Index Scan<\/strong>&#8221; na tabela &#8220;Person.Person&#8221; para realizar um &#8220;<strong>Index Seek<\/strong>&#8220;. Com isso podemos dizer que a coluna &#8220;<strong>FirstName<\/strong>&#8221; para essa consulta \u00e9 um predicado <strong>Sargable<\/strong>.<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_1.1.png?ssl=1\" rel=\"lightbox[1475]\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1479\" src=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_1.1.png?resize=678%2C150&#038;ssl=1\" alt=\"\" width=\"678\" height=\"150\" srcset=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_1.1.png?w=1353&amp;ssl=1 1353w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_1.1.png?resize=300%2C66&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_1.1.png?resize=768%2C170&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_1.1.png?resize=1024%2C226&amp;ssl=1 1024w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/a><\/p>\n<p>Mas aten\u00e7\u00e3o dependendo da consulta a coluna &#8220;FirstName&#8221; pode deixar de ser Sargable, principalmente quando utilizamos <strong>fun\u00e7\u00f5es ou utilizamos alguns operadores. <\/strong>Vejamos a query abaixo.<\/p>\n<pre class=\"lang:tsql decode:true\">SELECT B.FirstName,B.LastName,A.BirthDate\r\nFROM HumanResources.Employee A\r\nJOIN Person.Person B ON B.BusinessEntityID = A.BusinessEntityID\r\nWHERE LEFT(B.FirstName,5) = 'Paul'\r\n\r\n--Custo de execu\u00e7\u00e3o\r\nTable 'Employee'. Scan count 0, logical reads 18\r\nTable 'Person'. Scan count 1, logical reads 100\r\n SQL Server Execution Times: CPU time = 0 ms, elapsed time = 345 ms.<\/pre>\n<p>Neste primeiro exemplo &#8220;<strong>Non-Sargable<\/strong>&#8220;, estamos utilizando a fun\u00e7\u00e3o &#8220;<strong>LEFT<\/strong>&#8220;, com isso n\u00f3s impossibilitamos o otimizador de consulta a utilizar o \u00edndice para fazer a opera\u00e7\u00e3o de &#8220;<strong>Index Seek<\/strong>&#8220;.<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_2.png?ssl=1\" rel=\"lightbox[1475]\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1481\" src=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_2.png?resize=678%2C142&#038;ssl=1\" alt=\"\" width=\"678\" height=\"142\" srcset=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_2.png?w=1436&amp;ssl=1 1436w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_2.png?resize=300%2C63&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_2.png?resize=768%2C160&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_2.png?resize=1024%2C214&amp;ssl=1 1024w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_2.png?w=1356&amp;ssl=1 1356w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/a><\/p>\n<p>Nessa segunda consulta vamos realizar um SELECT que vai nos retornar todos os funcion\u00e1rios nascidos em 1980, para isso vamos criar um \u00edndice na coluna &#8220;<strong>BirthDate<\/strong>&#8221; da tabela &#8220;<strong>HumanResources.Employee<\/strong>&#8220;.<\/p>\n<pre class=\"theme:ssms2012 lang:tsql decode:true\">CREATE INDEX IX1_Employee ON HumanResources.Employee\r\n(BirthDate)\r\nWITH(FILLFACTOR=90)\r\n\r\nSELECT B.FirstName,B.LastName,A.BirthDate\r\nFROM HumanResources.Employee A\r\nJOIN Person.Person B ON B.BusinessEntityID = A.BusinessEntityID\r\nWHERE A.BirthDate BETWEEN '1980-01-01' AND '1980-12-31'\r\n\r\n--Custo da execu\u00e7\u00e3o\r\nTable 'Person'. Scan count 0, logical reads 21\r\nTable 'Employee'. Scan count 1, logical reads 2\r\n\r\n(1 row affected)\r\n\r\n SQL Server Execution Times:\r\n   CPU time = 0 ms,  elapsed time = 450 ms.\r\n<\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.png?ssl=1\" rel=\"lightbox[1475]\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1483\" src=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.png?resize=678%2C99&#038;ssl=1\" alt=\"\" width=\"678\" height=\"99\" srcset=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.png?w=1599&amp;ssl=1 1599w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.png?resize=300%2C44&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.png?resize=768%2C112&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.png?resize=1024%2C150&amp;ssl=1 1024w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.png?w=1356&amp;ssl=1 1356w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/a><\/p>\n<p>Como podemos observar, o SQL utilizou o \u00edndice para realizar uma opera\u00e7\u00e3o de &#8220;<strong>Index Seek<\/strong>&#8220;, ent\u00e3o o predicado &#8220;<strong>BirthDate<\/strong>&#8221; nesta consulta \u00e9 <strong>Sargable<\/strong>.<\/p>\n<p>Mas voc\u00ea pode estar pensando &#8220;P\u00f4 Tiago&#8221; da para deixar esse c\u00f3digo melhor utilizando a fun\u00e7\u00e3o &#8220;<strong>Year<\/strong>&#8220;, Ok&#8230;, vamos ver o que acontece se utilizarmos a fun\u00e7\u00e3o <strong>Year<\/strong>.<\/p>\n<pre class=\"theme:ssms2012 lang:tsql decode:true\">SELECT B.FirstName,B.LastName,A.BirthDate\r\nFROM HumanResources.Employee A\r\nJOIN Person.Person B ON B.BusinessEntityID = A.BusinessEntityID\r\nWHERE YEAR(A.BirthDate) = '1980'\r\n\r\n--Custo da execu\u00e7\u00e3o:\r\nTable 'Person'. Scan count 0, logical reads 21\r\nTable 'Employee'. Scan count 1, logical reads 88\r\n\r\n SQL Server Execution Times:\r\n   CPU time = 0 ms,  elapsed time = 554 ms.<\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.1.png?ssl=1\" rel=\"lightbox[1475]\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1492\" src=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.1.png?resize=678%2C100&#038;ssl=1\" alt=\"\" width=\"678\" height=\"100\" srcset=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.1.png?w=1424&amp;ssl=1 1424w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.1.png?resize=300%2C44&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.1.png?resize=768%2C114&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.1.png?resize=1024%2C152&amp;ssl=1 1024w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/Consulta_3.1.png?w=1356&amp;ssl=1 1356w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/a><\/p>\n<p>Novamente com a utiliza\u00e7\u00e3o da fun\u00e7\u00e3o &#8220;<strong>Year<\/strong>&#8221; no predicado &#8220;<strong>BirthDate<\/strong>&#8220;, o SQL <strong>N\u00c3O<\/strong> conseguiu realizar um Index Seek.<\/p>\n<p>Mas uma coisa a se observar \u00e9 que nem sempre \u00e9 ruim voc\u00ea &#8220;pagar&#8221;, usar uma fun\u00e7\u00e3o vai ter um momento que a diferen\u00e7a no custo ser\u00e1 t\u00e3o irrelevante que n\u00e3o vai justificar o trabalho de modificar toda a query. Outro ponto de aten\u00e7\u00e3o com o predicado Sargable, est\u00e1 relacionado a <strong>convers\u00e3o impl\u00edcita<\/strong>. Quando o SQL faz uma convers\u00e3o impl\u00edcita o otimizador de consulta <strong>N\u00c3O<\/strong> consegue realizar a opera\u00e7\u00e3o de <strong>Index Seek<\/strong>, tornando ele um predicado non-sargable, como podemos observar na consulta a seguir.<\/p>\n<pre class=\"theme:ssms2012 lang:tsql decode:true\">CREATE INDEX IX1_Customer ON sales.Customer\r\n(AccountNumber)\r\nWITH (FILLFACTOR = 90)\r\n\r\nSELECT b.FirstName,\r\n       b.LastName,\r\n       a.AccountNumber\r\nFROM sales.Customer a\r\n    JOIN Person.Person b\r\n        ON b.BusinessEntityID = a.PersonID\r\nWHERE a.AccountNumber = 'AW00029594';\r\n\r\n--Custo execu\u00e7\u00e3o:\r\nTable 'Person'. Scan count 0, logical reads 3\r\nTable 'Customer'. Scan count 1, logical reads 4\r\n\r\n SQL Server Execution Times:\r\n   CPU time = 0 ms,  elapsed time = 301 ms.<\/pre>\n<p>Na consulta acima criamos um \u00edndice na tabela &#8220;<strong>Sales.Custome<\/strong>r&#8221; utilizando a coluna &#8220;<strong>AccountNumber<\/strong>&#8221; como chave, ao executar a consulta podemos observar que o SQL utilizou o \u00edndice para fazer uma opera\u00e7\u00e3o de <strong>Index Seek<\/strong>.<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_4.png?ssl=1\" rel=\"lightbox[1475]\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1485\" src=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_4.png?resize=678%2C104&#038;ssl=1\" alt=\"\" width=\"678\" height=\"104\" srcset=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_4.png?w=1354&amp;ssl=1 1354w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_4.png?resize=300%2C46&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_4.png?resize=768%2C117&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_4.png?resize=1024%2C157&amp;ssl=1 1024w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/a><\/p>\n<p>Por\u00e9m \u00e9 normal quando o desenvolvedor utiliza algum <strong>framework<\/strong> at\u00e9 mesmo por costume colocar o par\u00e2metro &#8220;<strong>N<\/strong>&#8221; no varchar, quando fazemos isso estamos informando ao SQL que vamos trabalhar com\u00a0 o tipo de dados <strong>NVarchar<\/strong>, que neste caso vai gerar a <strong>convers\u00e3o impl\u00edcita<\/strong>, que vai fazer com que o SQL deixe de realizar o Index Seek no predicado e tamb\u00e9m consuma mais CPU para efetuar a consulta.<\/p>\n<pre class=\"theme:ssms2012 lang:tsql decode:true\">SELECT b.FirstName,\r\n       b.LastName,\r\n       a.AccountNumber\r\nFROM sales.Customer a\r\n    JOIN Person.Person b\r\n        ON b.BusinessEntityID = a.PersonID\r\nWHERE a.AccountNumber = N'AW00029594';\r\n\r\n--Custo de execu\u00e7\u00e3o:\r\nTable 'Person'. Scan count 0, logical reads 3\r\nTable 'Customer'. Scan count 1, logical reads 39\r\n\r\n SQL Server Execution Times:\r\n   CPU time = 63 ms,  elapsed time = 609 ms.<\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_4.1.png?ssl=1\" rel=\"lightbox[1475]\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1487\" src=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_4.1.png?resize=678%2C123&#038;ssl=1\" alt=\"\" width=\"678\" height=\"123\" srcset=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_4.1.png?w=1369&amp;ssl=1 1369w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_4.1.png?resize=300%2C55&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_4.1.png?resize=768%2C140&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_4.1.png?resize=1024%2C186&amp;ssl=1 1024w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/a><\/p>\n<p>Como podemos observar o SQL gerou um &#8220;<strong>warning<\/strong>&#8221; informando que o otimizador de consulta teve que fazer uma convers\u00e3o impl\u00edcita, e por consequ\u00eancia ele nem utilizou o \u00edndice que criamos na coluna &#8220;<strong>AccountNumber<\/strong>&#8220;, realizou um <strong>Index Scan<\/strong> no \u00edndice &#8220;IX_Customer_TerritoryID&#8221;. Al\u00e9m disso o custo de execu\u00e7\u00e3o na CPU aumentou praticamente 50%, ent\u00e3o quando ocorre uma <strong>convers\u00e3o impl\u00edcita<\/strong> no predicado temos um predicado non-sargable.<\/p>\n<p>Por isso que eu sempre recomendo a observar se no plano de execu\u00e7\u00e3o n\u00e3o tem nenhum warning referente a convers\u00e3o impl\u00edcita.<\/p>\n<p>Por fim&#8230; Existe um mito bastante comum que \u00e9 falar que quando utilizamos a cl\u00e1usula <strong>LIKE<\/strong> no predicado ele deixar de ser Sargable. Isso \u00e9 verdade, por\u00e9m somente se voc\u00ea <strong>utilizar o coringa &#8220;%&#8221; no come\u00e7o e no fim da sua string de busca.<\/strong> Vejamos no exemplo a seguir.<\/p>\n<p>A query abaixo \u00e9 a mesma que utilizamos no primeiro exemplo, por\u00e9m, desta vez queremos que o SQL nos retorne todos os clientes que tenha %Paul% no nome.<\/p>\n<pre class=\"theme:ssms2012 lang:tsql decode:true\">SELECT b.fullname,\r\n       a.AccountNumber\r\nFROM sales.Customer a\r\n    JOIN Person.Person b\r\n        ON b.BusinessEntityID = a.PersonID\r\nWHERE b.FullName LIKE ('%Paul%');\r\n\r\n--Custo:\r\nTable 'Customer'. Scan count 1, logical reads 123\r\nTable 'Person'. Scan count 1, logical reads 111\r\n\r\n SQL Server Execution Times:\r\n   CPU time = 31 ms,  elapsed time = 451 ms.<\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_5.png?ssl=1\" rel=\"lightbox[1475]\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1488\" src=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_5.png?resize=678%2C136&#038;ssl=1\" alt=\"\" width=\"678\" height=\"136\" srcset=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_5.png?w=1287&amp;ssl=1 1287w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_5.png?resize=300%2C60&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_5.png?resize=768%2C154&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_5.png?resize=1024%2C205&amp;ssl=1 1024w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/a><\/p>\n<p>Como utilizamos o no predicado <strong>FullName<\/strong> &#8220;<strong>%Paul%<\/strong>&#8220;, o otimizador de consulta <strong>N\u00c3O<\/strong> consegue efetuar um opera\u00e7\u00e3o de <strong>Index Seek<\/strong> no \u00edndice &#8220;<strong>IX02_Person<\/strong>&#8220;. Ent\u00e3o nesta consulta o predicado \u00e9 <strong>Non-Sargable<\/strong>, e at\u00e9 ai o mito que a cl\u00e1usula &#8220;<strong>LIKE<\/strong>&#8221; \u00e9 <strong>Non-Sargable<\/strong> \u00e9 verdade, mas&#8230;&#8230;<\/p>\n<p>Se voc\u00ea sabe quer somente o clientes que se chamam Paulo, Paul ou Paula, voc\u00ea concorda que podemos deixar essa consulta um pouco diferente, removendo o coringa &#8220;<strong>%<\/strong>&#8221; inicial, deixando apenas\u00a0<strong>FullName LIKE &#8220;Paul%&#8221;<\/strong>. Vamos ver o que o otimizador de consulta vai fazer nessa query.<\/p>\n<pre class=\"theme:ssms2012 lang:tsql decode:true\">SELECT b.fullname,\r\n       a.AccountNumber\r\nFROM sales.Customer a\r\n    JOIN Person.Person b\r\n        ON b.BusinessEntityID = a.PersonID\r\nWHERE b.FullName LIKE ('Paul%');\r\n\r\n--Custo:\r\nTable 'Customer'. Scan count 1, logical reads 123\r\nTable 'Person'. Scan count 1, logical reads 2\r\n\r\n SQL Server Execution Times:\r\n   CPU time = 16 ms,  elapsed time = 225 ms.<\/pre>\n<p><a href=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_5.1.png?ssl=1\" rel=\"lightbox[1475]\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1489\" src=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_5.1.png?resize=678%2C137&#038;ssl=1\" alt=\"\" width=\"678\" height=\"137\" srcset=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_5.1.png?w=1323&amp;ssl=1 1323w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_5.1.png?resize=300%2C61&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_5.1.png?resize=768%2C156&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2018\/10\/consulta_5.1.png?resize=1024%2C207&amp;ssl=1 1024w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/a><\/p>\n<p>Uauuuu agora o SQL conseguiu fazer uma opera\u00e7\u00e3o de <strong>Index Seek<\/strong> utilizando o \u00edndice &#8220;<strong>IX02_Person<\/strong>&#8220;, derrubando o mito que o <strong>LIKE<\/strong> <span style=\"color: #ff0000;\">SEMPRE<\/span> far\u00e1 que o predicado seja <strong>Non-Sargable<\/strong>.<\/p>\n<p>O <a href=\"https:\/\/fabriciolima.net\" target=\"_blank\" rel=\"noopener\">Fabricio Lima<\/a> tem um <a href=\"https:\/\/www.youtube.com\/watch?v=cyteAND34I0\" target=\"_blank\" rel=\"noopener\">v\u00eddeo<\/a> no que mostra dicas de como deixar o seu <strong>SELECT<\/strong> utilizando o <strong>LIKE<\/strong> mais perform\u00e1tico.<\/p>\n<p>Bom pessoal, por hoje \u00e9 isso espero ter contribu\u00eddo com algo novo para voc\u00eas.<\/p>\n<p>Deixe um feedback e nos ajude a melhorar.<\/p>\n<p>Abra\u00e7os,<\/p>\n<p>Tiago Neves<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ol\u00e1 pessoal tudo certo? No post de hoje vou compartilhar com voc\u00eas a respeito de um conceito muito comum no SQL Server, que \u00e9 o conceito de SARG (&#8220;S&#8220; search argument) e Non-SARGable cuja a tradu\u00e7\u00e3o livre pode ser &#8220;Argumento de busca&#8220;. O termo SARG nada mais \u00e9 que a coluna que voc\u00ea est\u00e1 utilizando [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"rop_custom_images_group":[],"rop_custom_messages_group":[],"rop_publish_now":"initial","rop_publish_now_accounts":{"twitter_91251433_91251433":""},"rop_publish_now_history":[],"rop_publish_now_status":"pending","_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpscppro_dont_share_socialmedia":false,"_wpscppro_custom_social_share_image":0,"_facebook_share_type":"","_twitter_share_type":"","_linkedin_share_type":"","_pinterest_share_type":"","_linkedin_share_type_page":"","_instagram_share_type":"","_medium_share_type":"","_threads_share_type":"","_google_business_share_type":"","_selected_social_profile":[],"_wpsp_enable_custom_social_template":false,"_wpsp_social_scheduling":{"enabled":false,"datetime":null,"platforms":[],"status":"template_only","dateOption":"today","timeOption":"now","customDays":"","customHours":"","customDate":"","customTime":"","schedulingType":"absolute"},"_wpsp_active_default_template":true},"categories":[2,220,16,26,20,239],"tags":[241,207,223,243,54,242,240],"class_list":["post-1475","post","type-post","status-publish","format-standard","hentry","category-casos-do-dia-a-dia","category-sql-server-2017","category-sqlserver-2014","category-sqlserver-2016","category-sqlserver-geral","category-tuning","tag-alwaystuningyourdata","tag-dba-es","tag-dba-remoto","tag-non-sarg","tag-performance","tag-sarg","tag-tuning"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p6eIyh-nN","jetpack-related-posts":[{"id":2414,"url":"https:\/\/www.tiagoneves.net\/blog\/sql-server-2016-esta-chegando-ao-fim-do-suporte-o-que-isso-significa-na-pratica\/","url_meta":{"origin":1475,"position":0},"title":"SQL Server 2016 est\u00e1 chegando ao fim do suporte: o que isso significa na pr\u00e1tica?","author":"tiagoneves","date":"27 de abril de 2026","format":false,"excerpt":"O SQL Server 2016 ter\u00e1 seu suporte estendido encerrado em 14 de julho de 2026, o que resultar\u00e1 na falta de atualiza\u00e7\u00f5es de seguran\u00e7a e suporte. Continuar usando essa vers\u00e3o traz riscos como vulnerabilidades e n\u00e3o conformidade regulat\u00f3ria. Planejar a migra\u00e7\u00e3o para vers\u00f5es mais recentes ou cloud deve ser prioridade\u2026","rel":"","context":"Em &quot;Seguran\u00e7a&quot;","block_context":{"text":"Seguran\u00e7a","link":"https:\/\/www.tiagoneves.net\/blog\/category\/seguranca\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2026\/04\/sql_server_2016_eos_v3.png?fit=772%2C702&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2026\/04\/sql_server_2016_eos_v3.png?fit=772%2C702&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2026\/04\/sql_server_2016_eos_v3.png?fit=772%2C702&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2026\/04\/sql_server_2016_eos_v3.png?fit=772%2C702&ssl=1&resize=700%2C400 2x"},"classes":[]}],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/posts\/1475","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/comments?post=1475"}],"version-history":[{"count":5,"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/posts\/1475\/revisions"}],"predecessor-version":[{"id":1493,"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/posts\/1475\/revisions\/1493"}],"wp:attachment":[{"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/media?parent=1475"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/categories?post=1475"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/tags?post=1475"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}