que causaria uma acentuada queda na performance. Para estimar esta quantidade de RAM, o QO leva em conta uma serie de fatores, dentre os quais pode entrar o tamanho dos dados que serao trabalhados. Se uma tabela e declarada com muitas colunas varchar(8000), o SQL Server nao sabe quanto espaco e usado em cada linha para esta coluna, entao toma uma media - 4.000 bytes de espaco usado por linha. Entao a estimativa do QO pode ser muito maior do que o tamanho da massa de dados - decorrente de uma modelagem "preguicosa". Isto incorre em maior uso de memoria e, em cenarios de pressao de memoria no servidor, em contencao ocorrendo entre as consultas - consultas bloqueadas esperando a liberacao da memoria estimada para sua execucao.O script a seguir demonstra isto. Copie ele para uma nova query no Management Studio (nao esqueca de mudar para um banco de testes), va executando os pedacos de codigo entre os comentarios e veja os resultados. Qualquer duvida posta uma pergunta!/* =============================================================================================================================== Alocacao errada de RAM devido a ma modelagem das colunas varchar. O Query Optimizer (QO) para execucao de determinadas consultas aloca RAM baseando-se no tamanho medio dos dados das colunas. No exemplo, ao usar varchar(8000), voce estara informando ao QO que o tamanho medio destas colunas e 4000 bytes. Alem disto, se o SQL Server esta sob pressao de memoria, pedidos de alocacao de grandes quantias de RAM podem gerar bloqueios (waits) por liberacao desta quantidade de memoria, o que pode impactar severamente a performance de execucao das queries. =============================================================================================================================== */-- Vamos simular um SQL Server com pressao de memoriaEXEC sp_configure 'max server memory'EXEC sp_configure 'show advanced options', 1reconfigureEXEC sp_configure 'max server memory', 1024 -- 1GB de RAM para o SQL ServerreconfigureGODROP TABLE TestMemoryGrant8000CREATE TABLE TestMemoryGrant8000(ID INT IDENTITY (1,1), Col1 VarChar(8000) DEFAULT NEWID() PRIMARY KEY, Col2 VarChar(8000) DEFAULT NEWID(), Col3 VarChar(8000) DEFAULT NEWID(), Col4 VarChar(8000) DEFAULT NEWID(), Col5 VarChar(8000) DEFAULT NEWID(), Col6 VarChar(8000) DEFAULT NEWID(), Col7 VarChar(8000) DEFAULT NEWID(), Col8 VarChar(8000) DEFAULT NEWID(), Col9 VarChar(8000) DEFAULT NEWID(), Col10 VarChar(8000) DEFAULT NEWID())GOINSERT INTO TestMemoryGrant8000 DEFAULT VALUESGO 5000-- Plano de execucao: Memory Grant no SELECT da 189MB. -- OBS: Tamanho de tabela nesse momento e 3MB (coluna page_count em sys.dm_db_index_physical_statsSELECT * FROM TestMemoryGrant8000 ORDER BY Col4SELECT * FROM sys.dm_db_index_physical_stats( DB_ID('Testes'), OBJECT_ID('TestMemoryGrant8000'), DEFAULT, DEFAULT, 'DETAILED')-- Mesma estrutura, tabela com tamanhos "certos" nas colunas varcharDROP TABLE TestMemoryGrant250CREATE TABLE TestMemoryGrant250(ID INT IDENTITY (1,1), Col1 VarChar(250) DEFAULT NEWID() PRIMARY KEY, Col2 VarChar(250) DEFAULT NEWID(), Col3 VarChar(250) DEFAULT NEWID(), Col4 VarChar(250) DEFAULT NEWID(), Col5 VarChar(250) DEFAULT NEWID(), Col6 VarChar(250) DEFAULT NEWID(), Col7 VarChar(250) DEFAULT NEWID(), Col8 VarChar(250) DEFAULT NEWID(), Col9 VarChar(250) DEFAULT NEWID(), Col10 VarChar(250) DEFAULT NEWID())GOINSERT INTO TestMemoryGrant250 DEFAULT VALUESGO 5000-- Plano de execucao: Memory Grant no SELECT da 8MB!!!SELECT * FROM TestMemoryGrant250 ORDER BY Col4-- Sintoma 2: Contencao por espaco em RAM-- Executar SELECTs no SQLQueryStress (http://www.datamanipulation.net/sqlquerystress/sqlquerystressdownload.asp)-- com 100 threads e 2 comandos. Vai ocorrer um monte de wait do tipo RESOURCE_SEMAPHORE na tabela com campos grandes -- (nao ocorre na tabela com campos pequenos)-- Notar a diferenca de tempo na execucao (sensivel mesmo em tabelas minusculas como