No SQL Server, as estatísticas são atualizadas automaticamente ao entrar Auto Update Statistics
( True
que é o padrão). Existe um motivo para atualizar as estatísticas manualmente e em quais circunstâncias?
Digamos que eu tenha um VARCHAR (que contém dados numéricos) que desejo usar para um cálculo simples (adicionando 10 a ele). De acordo com a documentação do MySQL sobre funções CAST , eu poderia fazer isso com um CAST ou um CONVERT:
SELECT (CAST(field1 AS SIGNED)) + 10
FROM myTable;
ou:
SELECT (CONVERT(field1,SIGNED)) + 10
FROM myTable;
Qual é a diferença entre CAST e CONVERT nesse sentido? Ambos estão realmente realizando a mesma coisa?
Eu tenho uma consulta bastante complexa que é executada em apenas alguns segundos por conta própria, mas quando agrupada em uma função com valor de tabela, é muito mais lenta; Na verdade, não deixei terminar, mas é executado por até dez minutos sem terminar. A única alteração é a substituição de duas variáveis de data (inicializadas com literais de data) por parâmetros de data:
Corre em Sete Segundos
DECLARE @StartDate DATE = '2011-05-21'
DECLARE @EndDate DATE = '2011-05-23'
DECLARE @Data TABLE (...)
INSERT INTO @Data(...) SELECT...
SELECT * FROM @Data
Funciona por pelo menos dez minutos
CREATE FUNCTION X (@StartDate DATE, @EndDate DATE)
RETURNS TABLE AS RETURN
SELECT ...
SELECT * FROM X ('2011-05-21', '2011-05-23')
Eu já havia escrito a função como um TVF de várias instruções com uma cláusula RETURNS @Data TABLE (...), mas trocá-la pela estrutura inline não fez uma alteração perceptível. O tempo de execução longo do TVF é o SELECT * FROM X
tempo real; na verdade, criar o UDF leva apenas alguns segundos.
Eu poderia postar a consulta em questão, mas é um pouco longa (~ 165 linhas) e, com base no sucesso da primeira abordagem, suspeito que algo mais esteja acontecendo. Folheando os planos de execução, eles parecem ser idênticos.
Tentei dividir a consulta em seções menores, sem alteração. Nenhuma seção única leva mais do que alguns segundos quando executada sozinha, mas o TVF ainda trava.
Vejo uma pergunta muito semelhante, https://stackoverflow.com/questions/4190506/sql-server-2005-table-valued-function-weird-performance , mas não tenho certeza de que a solução se aplica. Talvez alguém tenha visto esse problema e conheça uma solução mais geral? Obrigado!
Aqui está o dm_exec_requests após vários minutos de processamento:
session_id 59
request_id 0
start_time 40688.46517
status running
command UPDATE
sql_handle 0x030015002D21AF39242A1101ED9E00000000000000000000
statement_start_offset 10962
statement_end_offset 16012
plan_handle 0x050015002D21AF3940C1E6B0040000000000000000000000
database_id 21
user_id 1
connection_id 314AE0E4-A1FB-4602-BF40-02D857BAD6CF
blocking_session_id 0
wait_type NULL
wait_time 0
last_wait_type SOS_SCHEDULER_YIELD
wait_resource
open_transaction_count 0
open_resultset_count 1
transaction_id 48030651
context_info 0x
percent_complete 0
estimated_completion_time 0
cpu_time 344777
total_elapsed_time 348632
scheduler_id 7
task_address 0x000000045FC85048
reads 1549
writes 13
logical_reads 30331425
text_size 2147483647
language us_english
date_format mdy
date_first 7
quoted_identifier 1
arithabort 1
ansi_null_dflt_on 1
ansi_defaults 0
ansi_warnings 1
ansi_padding 1
ansi_nulls 1
concat_null_yields_null 1
transaction_isolation_level 2
lock_timeout -1
deadlock_priority 0
row_count 105
prev_error 0
nest_level 1
granted_query_memory 170
executing_managed_code 0
group_id 2
query_hash 0xBE6A286546AF62FC
query_plan_hash 0xD07630B947043AF0
Aqui está a consulta completa:
CREATE FUNCTION Routine.MarketingDashboardECommerceBase (@StartDate DATE, @EndDate DATE)
RETURNS TABLE AS RETURN
WITH RegionsByCode AS (SELECT CountryCode, MIN(Region) AS Region FROM Staging.Volusion.MarketingRegions GROUP BY CountryCode)
SELECT
D.Date, Div.Division, Region.Region, C.Category1, C.Category2, C.Category3,
COALESCE(V.Visits, 0) AS Visits,
COALESCE(Dem.Demos, 0) AS Demos,
COALESCE(S.GrossStores, 0) AS GrossStores,
COALESCE(S.PaidStores, 0) AS PaidStores,
COALESCE(S.NetStores, 0) AS NetStores,
COALESCE(S.StoresActiveNow, 0) AS StoresActiveNow
-- This line causes the run time to climb from a few seconds to over an hour!
--COALESCE(V.Visits, 0) * COALESCE(ACS.AvgClickCost, GAAC.AvgAdCost, 0.00) AS TotalAdCost
-- This line alone does not inflate the run time
--ACS.AvgClickCost
-- This line is enough to increase the run time to at least a couple minutes
--GAAC.AvgAdCost
FROM
--Dates AS D
(SELECT SQLDate AS Date FROM Dates WHERE SQLDate BETWEEN @StartDate AND @EndDate) AS D
CROSS JOIN (SELECT 'UK' AS Division UNION SELECT 'US' UNION SELECT 'IN' UNION SELECT 'Unknown') AS Div
CROSS JOIN (SELECT Category1, Category2, Category3 FROM Routine.MarketingDashboardCampaignMap UNION SELECT 'Unknown', 'Unknown', 'Unknown') AS C
CROSS JOIN (SELECT DISTINCT Region FROM Staging.Volusion.MarketingRegions) AS Region
-- Visitors
LEFT JOIN
(
SELECT
V.Date,
CASE WHEN V.Country IN ('United Kingdom', 'Guernsey', 'Ireland', 'Jersey') THEN 'UK'
WHEN V.Country IN ('United States', 'Canada', 'Puerto Rico', 'U.S. Virgin Islands') THEN 'US'
ELSE 'IN' END AS Division,
COALESCE(MR.Region, 'Unknown') AS Region,
C.Category1, C.Category2, C.Category3,
SUM(V.Visits) AS Visits
FROM
RawData.GoogleAnalytics.Visits AS V
INNER JOIN Routine.MarketingDashboardCampaignMap AS C ON V.LandingPage = C.LandingPage AND V.Campaign = C.Campaign AND V.Medium = C.Medium AND V.Referrer = C.Referrer AND V.Source = C.Source
LEFT JOIN Staging.Volusion.MarketingRegions AS MR ON V.Country = MR.CountryName
WHERE
V.Date BETWEEN @StartDate AND @EndDate
GROUP BY
V.Date,
CASE WHEN V.Country IN ('United Kingdom', 'Guernsey', 'Ireland', 'Jersey') THEN 'UK'
WHEN V.Country IN ('United States', 'Canada', 'Puerto Rico', 'U.S. Virgin Islands') THEN 'US'
ELSE 'IN' END,
COALESCE(MR.Region, 'Unknown'), C.Category1, C.Category2, C.Category3
) AS V ON D.Date = V.Date AND Div.Division = V.Division AND Region.Region = V.Region AND C.Category1 = V.Category1 AND C.Category2 = V.Category2 AND C.Category3 = V.Category3
-- Demos
LEFT JOIN
(
SELECT
OD.SQLDate,
G.Division,
COALESCE(MR.Region, 'Unknown') AS Region,
COALESCE(C.Category1, 'Unknown') AS Category1,
COALESCE(C.Category2, 'Unknown') AS Category2,
COALESCE(C.Category3, 'Unknown') AS Category3,
SUM(D.Demos) AS Demos
FROM
Demos AS D
INNER JOIN Orders AS O ON D."Order" = O."Order"
INNER JOIN Dates AS OD ON O.OrderDate = OD.DateSerial
INNER JOIN MarketingSources AS MS ON D.Source = MS.Source
LEFT JOIN RegionsByCode AS MR ON MS.CountryCode = MR.CountryCode
LEFT JOIN
(
SELECT
G.TransactionID,
MIN (
CASE WHEN G.Country IN ('United Kingdom', 'Guernsey', 'Ireland', 'Jersey') THEN 'UK'
WHEN G.Country IN ('United States', 'Canada', 'Puerto Rico', 'U.S. Virgin Islands') THEN 'US'
ELSE 'IN' END
) AS Division
FROM
RawData.GoogleAnalytics.Geography AS G
WHERE
TransactionDate BETWEEN @StartDate AND @EndDate
AND NOT EXISTS (SELECT * FROM RawData.GoogleAnalytics.Geography AS G2 WHERE G.TransactionID = G2.TransactionID AND G2.EffectiveDate > G.EffectiveDate)
GROUP BY
G.TransactionID
) AS G ON O.VolusionOrderID = G.TransactionID
LEFT JOIN RawData.GoogleAnalytics.Referrers AS R ON O.VolusionOrderID = R.TransactionID AND NOT EXISTS (SELECT * FROM RawData.GoogleAnalytics.Referrers AS R2 WHERE R.TransactionID = R2.TransactionID AND R2.EffectiveDate > R.EffectiveDate)
LEFT JOIN Routine.MarketingDashboardCampaignMap AS C ON MS.LandingPage = C.LandingPage AND MS.Campaign = C.Campaign AND MS.Medium = C.Medium AND COALESCE(R.ReferralPath, '(not set)') = C.Referrer AND MS.SourceName = C.Source
WHERE
O.IsDeleted = 'No'
AND OD.SQLDate BETWEEN @StartDate AND @EndDate
GROUP BY
OD.SQLDate,
G.Division,
COALESCE(MR.Region, 'Unknown'),
COALESCE(C.Category1, 'Unknown'),
COALESCE(C.Category2, 'Unknown'),
COALESCE(C.Category3, 'Unknown')
) AS Dem ON D.Date = Dem.SQLDate AND Div.Division = Dem.Division AND Region.Region = Dem.Region AND C.Category1 = Dem.Category1 AND C.Category2 = Dem.Category2 AND C.Category3 = Dem.Category3
-- Stores
LEFT JOIN
(
SELECT
OD.SQLDate,
CASE WHEN O.VolusionCountryCode = 'GB' THEN 'UK'
WHEN A.CountryShortName IN ('U.S.', 'Canada', 'Puerto Rico', 'U.S. Virgin Islands') THEN 'US'
ELSE 'IN' END AS Division,
COALESCE(MR.Region, 'Unknown') AS Region,
COALESCE(CpM.Category1, 'Unknown') AS Category1,
COALESCE(CpM.Category2, 'Unknown') AS Category2,
COALESCE(CpM.Category3, 'Unknown') AS Category3,
SUM(S.Stores) AS GrossStores,
SUM(CASE WHEN O.DatePaid <> -1 THEN 1 ELSE 0 END) AS PaidStores,
SUM(CASE WHEN O.DatePaid <> -1 AND CD.WeekEnding <> OD.WeekEnding THEN 1 ELSE 0 END) AS NetStores,
SUM(CASE WHEN O.DatePaid <> -1 THEN SH.ActiveStores ELSE 0 END) AS StoresActiveNow
FROM
Stores AS S
INNER JOIN Orders AS O ON S."Order" = O."Order"
INNER JOIN Dates AS OD ON O.OrderDate = OD.DateSerial
INNER JOIN Dates AS CD ON O.CancellationDate = CD.DateSerial
INNER JOIN Customers AS C ON O.CustomerNow = C.Customer
INNER JOIN MarketingSources AS MS ON C.Source = MS.Source
INNER JOIN StoreHistory AS SH ON S.MostRecentHistory = SH.History
INNER JOIN Addresses AS A ON C.Address = A.Address
LEFT JOIN RegionsByCode AS MR ON MS.CountryCode = MR.CountryCode
LEFT JOIN Routine.MarketingDashboardCampaignMap AS CpM ON CpM.LandingPage = 'N/A' AND MS.Campaign = CpM.Campaign AND MS.Medium = CpM.Medium AND CpM.Referrer = 'N/A' AND MS.SourceName = CpM.Source
WHERE
O.IsDeleted = 'No'
AND OD.SQLDate BETWEEN @StartDate AND @EndDate
GROUP BY
OD.SQLDate,
CASE WHEN O.VolusionCountryCode = 'GB' THEN 'UK'
WHEN A.CountryShortName IN ('U.S.', 'Canada', 'Puerto Rico', 'U.S. Virgin Islands') THEN 'US'
ELSE 'IN' END,
COALESCE(MR.Region, 'Unknown'),
COALESCE(CpM.Category1, 'Unknown'),
COALESCE(CpM.Category2, 'Unknown'),
COALESCE(CpM.Category3, 'Unknown')
) AS S ON D.Date = S.SQLDate AND Div.Division = S.Division AND Region.Region = S.Region AND C.Category1 = S.Category1 AND C.Category2 = S.Category2 AND C.Category3 = S.Category3
-- Google Analytics spend
LEFT JOIN
(
SELECT
AC.Date, C.Category1, C.Category2, C.Category3, SUM(AC.AdCost) / SUM(AC.Visits) AS AvgAdCost
FROM
RawData.GoogleAnalytics.AdCosts AS AC
INNER JOIN
(
SELECT Campaign, Medium, Source, MIN(Category1) AS Category1, MIN(Category2) AS Category2, MIN(Category3) AS Category3
FROM Routine.MarketingDashboardCampaignMap
WHERE Category1 <> 'Affiliate'
GROUP BY Campaign, Medium, Source
) AS C ON AC.Campaign = C.Campaign AND AC.Medium = C.Medium AND AC.Source = C.Source
WHERE
AC.Date BETWEEN @StartDate AND @EndDate
GROUP BY
AC.Date, C.Category1, C.Category2, C.Category3
HAVING
SUM(AC.AdCost) > 0.00 AND SUM(AC.Visits) > 0
) AS GAAC ON D.Date = GAAC.Date AND C.Category1 = GAAC.Category1 AND C.Category2 = GAAC.Category2 AND C.Category3 = GAAC.Category3
-- adCenter spend
LEFT JOIN
(
SELECT Date, SUM(Spend) / SUM(Clicks) AS AvgClickCost
FROM RawData.AdCenter.Spend
WHERE Date BETWEEN @StartDate AND @EndDate
GROUP BY Date
HAVING SUM(Spend) > 0.00 AND SUM(Clicks) > 0
) AS ACS ON D.Date = ACS.Date AND C.Category1 = 'PPC' AND C.Category2 = 'adCenter' AND C.Category3 = 'N/A'
WHERE
V.Visits > 0 OR Dem.Demos > 0 OR S.GrossStores > 0
GO
SELECT * FROM Routine.MarketingDashboardECommerceBase('2011-05-21', '2011-05-23')
Pesquisando na web, encontrei conselhos conflitantes sobre se há um impacto no desempenho ao especificar VARCHAR
colunas excessivamente largas, por exemplo VARCHAR(255)
, quando VARCHAR(30)
provavelmente será o suficiente.
Eu vejo consistentemente que há um impacto no desempenho se a linha inteira exceder 8060 bytes. Fora isso, vejo discordância.
A afirmação é verdadeira de que o padrão é SET ANSI PADDING ON
= potencial para muitos espaços à direita ? Contanto que a largura total da linha seja menor que 8060, há alguma preocupação real de desempenho em VARCHAR
colunas superdimensionadas?
Evidência de que a largura da coluna é importante
O mesmo vale para os tipos de dados CHAR e VARCHAR. Não especifique mais caracteres nas colunas de caracteres que você precisa.
https://www.sql-server-performance.com/w2k-filesystem-affects-performance/
- Comprimento é uma restrição nos dados (como CHECK, FK, NULL etc)
- Desempenho quando a linha excede 8060 bytes
- Não pode ter restrição ou índice exclusivo (a largura da coluna chave deve ser < 900)
- O padrão é
SET ANSI PADDING ON
= potencial para muitos espaços à direita
Quais são as consequências da configuração de varchar(8000)?
Evidência de que a largura da coluna NÃO importa
Se você está falando sobre varchar e nvarchar, não, não há penalidade por permitir um comprimento de campo maior.
https://stackoverflow.com/questions/7025996/overstating-field-size-in-database-design
O tipo de dados varchar, por outro lado, consome apenas a quantidade de espaço real usado mais 2 bytes para sobrecarga
http://sqlfool.com/content/PerformanceConsiderationsOfDataTypes.pdf
O banco de dados em que nossos desenvolvedores estão trabalhando é muito grande (tem muitos objetos de banco de dados). Temos que controlar as alterações dos objetos do banco de dados (gerenciamento de alterações). Nossa empresa não pode ter uma pessoa que seja responsável apenas por alterações no banco de dados. Portanto, precisamos de uma fonte segura para objetos de banco de dados, algo como controle de versão para código padrão, mas mais relacionado ao banco de dados, que possa sincronizar banco de dados e scripts. Qual é o melhor. Confiável, Barato, Funcional - escolha os dois :)
Quando uso um Varchar com espaços ele ignora os espaços no final.
ex:
declare @X varchar(50)
Este...
set @X= 'John'
...é o mesmo que...
set @X= 'John '
Ele os considera iguais. Como posso fazer com que o sistema os reconheça como diferentes?
Eu tenho tabelas Log e LogItem; Estou escrevendo uma consulta para pegar alguns dados de ambos. São milhares Logs
e cada um Log
pode ter até 125LogItems
A consulta em questão é complicada, então estou pulando (se alguém achar que é importante, provavelmente posso postá-la), mas quando executei o plano SSMS Estimated Query, ele me disse que um novo índice não clusterizado melhoraria o desempenho em até 100% .
Existing Index: Non-clustered
Key Colums (LogItem): ParentLogID, DateModified, Name, DatabaseModified
Query Plan Recommendation
CREATE NONCLUSTERED INDEX [LogReportIndex]
ON [dbo].[LogItem] ([ParentLogID],[DatabaseModified])
Apenas por diversão, criei este novo índice e executei a consulta e, para minha surpresa, agora leva cerca de 1 segundo para minha consulta ser executada, quando antes levava mais de 10 segundos.
Presumi que meu índice existente cobriria essa nova consulta, então minha pergunta é por que a criação de um novo índice nas únicas colunas usadas em minha nova consulta melhorou o desempenho? Devo ter um índice para cada combinação exclusiva de colunas usadas em minhas where
cláusulas?
nota: não acho que seja porque o SQL Server está armazenando em cache meus resultados, executei a consulta cerca de 25 a 30 vezes antes de criar o índice e demorou consistentemente de 10 a 15 segundos, após o índice agora é consistentemente ~ 1 ou menos.
Não consigo encontrar opção(ões) diretamente para definir UTF-8
relacionadas Collations/Charsets
no SQL Server 2005/2008, da mesma forma que é possível definir em outros mecanismos SQL, mas no SQL Server 2005/2008 existem apenas agrupamentos latinos e SQL.
Existe alguma opção para forçar/instalar esses agrupamentos / conjuntos de caracteres no mecanismo do SQL Server (para ambas as versões) 2005/2008 no sistema operacional Win2008
Estou tentando criar uma tabela no Management Studio e depois de ler sobre a nova função (do SQL 2005 em diante) NEWSEQUENTIALID()
, pensei em tentar.
Isto é o que estou fazendo:
Mas não está me deixando. A mensagem de erro que recebo é:
'FormTemplate (Forms)' table - Error validating the default for column 'FormTemplateId'.
Estou perdendo um truque aqui? Definitivamente, estou executando o SQL Server 2008 R2.
O caso é simples: você tem um banco de dados MySQL onde possui apenas uma interface de consulta SQL e deseja conhecer a estrutura do banco de dados com consultas. Você pode listar tabelas com show tables;
comando, mas como você vê os nomes das colunas individuais?
( a SELECT
instrução mostra Empty set
se nenhum dado está presente e NÃO pode ser usado.)