Com o lançamento recente do MySQL 8, não consigo encontrar nenhuma informação sobre por que as versões 6 e 7 foram ignoradas. Ninguem sabe?
Eu tenho uma varchar
coluna em uma tabela no SQL Server que contém uma string de texto codificada em base64 que eu gostaria de decodificar em seu equivalente de texto simples
O SQL Server tem alguma funcionalidade nativa para lidar com esse tipo de coisa?
Uma string base64 de amostra:
cm9sZToxIHByb2R1Y2VyOjEyIHRpbWVzdGFtcDoxNDY4NjQwMjIyNTcxMDAwIGxhdGxuZ3tsYXRpdHVkZV9lNzo0MTY5ODkzOTQgbG9uZ2l0dWRlX2U3Oi03Mzg5NjYyMTB9IHJhZGl1czoxOTc2NA==
Que decodifica para:
role:1 producer:12 timestamp:1468640222571000 latlng{latitude_e7:416989394 longitude_e7:-738966210} radius:19764
Esta pergunta é diferente, mas semelhante a esta solicitação que procura SQL-89 .
O primeiro rascunho do SQL é rotulado como SQL-86. Inúmeras referências são feitas a ele. Isso está disponível para download? A Wikipedia nem sequer tem uma página para isso. Estou interessado nele por razões históricas.
Parece ser chamado também
- ANSI X3.135-1986
- CAN/CSA Z243.47-88
- ISO 9075:1987
- SQL/1
- NBS FIPS 127
A especificação é citada em documentos do período como proveniente do Comitê Técnico ANSI X3H2 .
Eu sei que existe webstore.ansi.org, mas não consigo encontrar o X3.135-1986
documento. No entanto, posso encontrar X3.168-1989
especificações disponíveis emX3.135-1992
Procurando por both X3.168
, e X3.135
não me permitem comprar as especificações de 1986.
Podemos armazenar informações de data e hora de duas maneiras. Qual é a melhor abordagem para armazenar informações de DateTime?
Armazenando data e hora em 2 colunas separadas ou uma coluna usando DateTime ?
Você pode explicar por que essa abordagem é melhor?
(Link para documentos do MySQL para referência, a pergunta é geral, não específica para o MySQL)
Tipos de data e hora: Data e hora
Nas consultas abaixo, estima-se que ambos os planos de execução executem 1.000 buscas em um índice exclusivo.
As buscas são conduzidas por uma varredura ordenada na mesma tabela de origem, portanto, aparentemente, devem acabar buscando os mesmos valores na mesma ordem.
Ambos os loops aninhados têm<NestedLoops Optimized="false" WithOrderedPrefetch="true">
Alguém sabe por que essa tarefa custa 0,172434 no primeiro plano, mas 3,01702 no segundo?
(O motivo da pergunta é que a primeira consulta foi sugerida para mim como uma otimização devido ao aparente custo de plano muito menor. Na verdade, parece-me que funciona mais, mas estou apenas tentando explicar a discrepância. .)
Configurar
CREATE TABLE dbo.Target(KeyCol int PRIMARY KEY, OtherCol char(32) NOT NULL);
CREATE TABLE dbo.Staging(KeyCol int PRIMARY KEY, OtherCol char(32) NOT NULL);
INSERT INTO dbo.Target
SELECT TOP (1000000) ROW_NUMBER() OVER (ORDER BY @@SPID), LEFT(NEWID(),32)
FROM master..spt_values v1,
master..spt_values v2;
INSERT INTO dbo.Staging
SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY @@SPID), LEFT(NEWID(),32)
FROM master..spt_values v1;
Consulta 1 link "Colar o plano"
WITH T
AS (SELECT *
FROM Target AS T
WHERE T.KeyCol IN (SELECT S.KeyCol
FROM Staging AS S))
MERGE T
USING Staging S
ON ( T.KeyCol = S.KeyCol )
WHEN NOT MATCHED THEN
INSERT ( KeyCol, OtherCol )
VALUES(S.KeyCol, S.OtherCol )
WHEN MATCHED AND T.OtherCol > S.OtherCol THEN
UPDATE SET T.OtherCol = S.OtherCol;
Consulta 2 link "Colar o plano"
MERGE Target T
USING Staging S
ON ( T.KeyCol = S.KeyCol )
WHEN NOT MATCHED THEN
INSERT ( KeyCol, OtherCol )
VALUES( S.KeyCol, S.OtherCol )
WHEN MATCHED AND T.OtherCol > S.OtherCol THEN
UPDATE SET T.OtherCol = S.OtherCol;
Consulta 1
Consulta 2
O acima foi testado no SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64)
@Joe Obbish aponta nos comentários que uma reprodução mais simples seria
SELECT *
FROM staging AS S
LEFT OUTER JOIN Target AS T
ON T.KeyCol = S.KeyCol;
vs
SELECT *
FROM staging AS S
LEFT OUTER JOIN (SELECT * FROM Target) AS T
ON T.KeyCol = S.KeyCol;
Para a tabela de preparação de 1.000 linhas, ambos os itens acima ainda têm a mesma forma de plano com loops aninhados e o plano sem a tabela derivada parecendo mais barato, mas para uma tabela de preparação de 10.000 linhas e a mesma tabela de destino acima, a diferença nos custos altera o plano forma (com uma varredura completa e junção de mesclagem parecendo relativamente mais atraente do que buscas caras) mostrando essa discrepância de custo pode ter outras implicações além de apenas dificultar a comparação de planos.
Estou precisando encontrar um caminho para SUM()
todos os valores positivos num
e retornar o valor SUM()
de todos os números positivos e uma linha individual para cada número negativo. Abaixo está um exemplo de DDL:
Create Table #Be
(
id int
, salesid int
, num decimal(16,4)
)
Insert Into #BE Values
(1, 1, 12.32), (2, 1, -13.00), (3, 1, 14.00)
, (4, 2, 12.12), (5, 2, 14.00), (6, 2, 21.23)
, (7, 3, -12.32), (8,3, -43.23), (9, 3, -2.32)
E esta é a minha saída desejada (números positivos para cada salesid SUM()
e negativos obtêm uma linha individual retornada):
salesid num
1 26.32
1 -13.00
2 47.35
3 -12.32
3 -43.23
3 -2.32
Considere o seguinte plano de consulta no SQL Server 2014:
No plano de consulta, uma junção automática ar.fId = ar.fId
produz uma estimativa de 1 linha. No entanto, esta é uma estimativa logicamente inconsistente: ar
tem 20,608
linhas e apenas um valor distinto de fId
(refletido com precisão nas estatísticas). Portanto, essa junção produz o produto cruzado completo de linhas ( ~424MM
linhas), fazendo com que a consulta seja executada por várias horas.
Estou tendo dificuldade em entender por que o SQL Server apresentaria uma estimativa que pode ser facilmente comprovada como inconsistente com as estatísticas. Alguma ideia?
Investigação inicial e detalhes adicionais
Com base na resposta de Paul aqui , parece que as heurísticas SQL 2012 e SQL 2014 para estimar a cardinalidade da junção devem lidar facilmente com uma situação em que dois histogramas idênticos precisam ser comparados.
Comecei com a saída do sinalizador de rastreamento 2363, mas não consegui entender isso facilmente. O trecho a seguir significa que o SQL Server está comparando histogramas para fId
e bId
para estimar a seletividade de uma junção que usa apenas fId
? Se assim for, isso obviamente não seria correto. Ou estou interpretando mal a saída do sinalizador de rastreamento?
Plan for computation:
CSelCalcExpressionComparedToExpression( QCOL: [ar].fId x_cmpEq QCOL: [ar].fId )
Loaded histogram for column QCOL: [ar].bId from stats with id 3
Loaded histogram for column QCOL: [ar].fId from stats with id 1
Selectivity: 0
Observe que criei várias soluções alternativas, que são incluídas no script de reprodução completo e reduzem essa consulta para milissegundos. Esta pergunta é focada em entender o comportamento, como evitá-lo em consultas futuras e determinar se é um bug que deve ser registrado na Microsoft.
Aqui está um script de reprodução completo , aqui está a saída completa do sinalizador de rastreamento 2363 e aqui estão as definições de consulta e tabela, caso você queira examiná-las rapidamente sem abrir o script completo:
WITH cte AS (
SELECT ar.fId,
ar.bId,
MIN(CONVERT(INT, ar.isT)) AS isT,
MAX(CONVERT(INT, tcr.isS)) AS isS
FROM #SQL2014MinMaxAggregateCardinalityBug_ar ar
LEFT OUTER JOIN #SQL2014MinMaxAggregateCardinalityBug_tcr tcr
ON tcr.rId = 508
AND tcr.fId = ar.fId
AND tcr.bId = ar.bId
GROUP BY ar.fId, ar.bId
)
SELECT s.fId, s.bId, s.isS, t.isS
FROM cte s
JOIN cte t
ON t.fId = s.fId
AND t.isT = 1
CREATE TABLE #SQL2014MinMaxAggregateCardinalityBug_ar (
fId INT NOT NULL,
bId INT NOT NULL,
isT BIT NOT NULL
PRIMARY KEY (fId, bId)
)
CREATE TABLE #SQL2014MinMaxAggregateCardinalityBug_tcr (
rId INT NOT NULL,
fId INT NOT NULL,
bId INT NOT NULL,
isS BIT NOT NULL
PRIMARY KEY (rId, fId, bId, isS)
)
TL;DR: A questão abaixo se resume a: Ao inserir uma linha, existe uma janela de oportunidade entre a geração de um novo Identity
valor e o bloqueio da chave da linha correspondente no índice clusterizado, onde um observador externo poderia ver uma nova Identity
valor inserido por uma transação concorrente? (No SQL Server.)
versão detalhada
Eu tenho uma tabela do SQL Server com uma Identity
coluna chamada CheckpointSequence
, que é a chave do índice clusterizado da tabela (que também possui vários índices não clusterizados adicionais). As linhas são inseridas na tabela por vários processos e threads simultâneos (no nível de isolamento READ COMMITTED
e sem IDENTITY_INSERT
). Ao mesmo tempo, existem processos que leem periodicamente as linhas do índice clusterizado, ordenadas por aquela CheckpointSequence
coluna (também em nível de isolamento READ COMMITTED
, com a READ COMMITTED SNAPSHOT
opção desativada).
Atualmente, confio no fato de que os processos de leitura nunca podem "pular" um ponto de verificação. A minha dúvida é: Posso contar com este imóvel? E se não, o que eu poderia fazer para torná-lo verdade?
Exemplo: Ao inserir linhas com valores de identidade 1, 2, 3, 4 e 5, o leitor não deve ver a linha com valor 5 antes de ver a linha com valor 4. Os testes mostram que a consulta, que contém uma ORDER BY CheckpointSequence
cláusula ( e uma WHERE CheckpointSequence > -1
cláusula), bloqueia de forma confiável sempre que a linha 4 deve ser lida, mas ainda não confirmada, mesmo que a linha 5 já tenha sido confirmada.
Acredito que, pelo menos em teoria, pode haver uma condição de corrida aqui que pode fazer com que essa suposição seja quebrada. Infelizmente, a documentação Identity
não diz muito sobre como Identity
funciona no contexto de várias transações simultâneas, apenas diz "Cada novo valor é gerado com base na semente e incremento atuais". e "Cada novo valor para uma determinada transação é diferente de outras transações simultâneas na tabela." ( MSDN )
Meu raciocínio é que deve funcionar de alguma forma assim:
- Uma transação é iniciada (explícita ou implicitamente).
- Um valor de identidade (X) é gerado.
- O bloqueio de linha correspondente é obtido no índice clusterizado com base no valor de identidade (a menos que o escalonamento de bloqueio seja ativado, caso em que toda a tabela é bloqueada).
- A linha é inserida.
- A transação é confirmada (possivelmente muito tempo depois), então o bloqueio é removido novamente.
Acho que entre os passos 2 e 3, há uma janela muito pequena onde
- uma sessão simultânea pode gerar o próximo valor de identidade (X+1) e executar todas as etapas restantes,
- permitindo assim que um leitor vindo exatamente naquele ponto do tempo leia o valor X+1, perdendo o valor de X.
Claro, a probabilidade disso parece extremamente baixa; mas ainda assim - isso pode acontecer. Ou poderia?
(Se você estiver interessado no contexto: esta é a implementação do SQL Persistence Engine do NEventStore. O NEventStore implementa um armazenamento de evento apenas anexado, onde cada evento obtém um novo número de sequência de ponto de verificação ascendente. Os clientes leem os eventos do armazenamento de eventos ordenados por ponto de verificação para realizar cálculos de todos os tipos. Depois que um evento com ponto de verificação X é processado, os clientes consideram apenas eventos "mais recentes", ou seja, eventos com ponto de verificação X+1 e acima. Portanto, é vital que os eventos nunca possam ser ignorados, como eles nunca seriam considerados novamente. No momento, estou tentando determinar se a Identity
implementação do ponto de verificação com base atende a esse requisito. Estas são as instruções SQL exatas usadas : Schema , Writer's query ,Pergunta do Leitor .)
Se eu estiver certo e a situação descrita acima puder surgir, vejo apenas duas opções de lidar com eles, ambas insatisfatórias:
- Ao ver um valor de sequência de ponto de verificação X+1 antes de ter visto X, descarte X+1 e tente novamente mais tarde. No entanto, porque
Identity
é claro que pode produzir lacunas (por exemplo, quando a transação é revertida), X pode nunca vir. - Então, mesma abordagem, mas aceite o intervalo após n milissegundos. No entanto, que valor de n devo assumir?
Alguma ideia melhor?
Estou testando a exclusão de dados de um índice columnstore clusterizado.
Percebi que há um grande operador de spool ansioso no plano de execução:
Isso se completa com as seguintes características:
- 60 milhões de linhas excluídas
- 1,9 GiB TempDB usado
- 14 minutos de tempo de execução
- plano de série
- 1 reencadernação no carretel
- Custo estimado para digitalização: 364.821
Se eu induzir o estimador a subestimar, obtenho um plano mais rápido que evita o uso do TempDB:
Custo estimado da varredura: 56.901
(Este é um plano estimado, mas os números nos comentários estão corretos.)
Curiosamente, o spool desaparece novamente se eu liberar os armazenamentos delta executando o seguinte:
ALTER INDEX IX_Clustered ON Fact.RecordedMetricsDetail REORGANIZE WITH (COMPRESS_ALL_ROW_GROUPS = ON);
O spool parece ser introduzido apenas quando há mais do que algum limite de páginas nos armazenamentos delta.
Para verificar o tamanho dos armazenamentos delta, estou executando a seguinte consulta para verificar as páginas in-row da tabela:
SELECT
SUM([in_row_used_page_count]) AS in_row_used_pages,
SUM(in_row_data_page_count) AS in_row_data_pages
FROM sys.[dm_db_partition_stats] as pstats
JOIN sys.partitions AS p
ON pstats.partition_id = p.partition_id
WHERE p.[object_id] = OBJECT_ID('Fact.RecordedMetricsDetail');
Existe algum benefício plausível para o iterador de spool no primeiro plano? Devo presumir que se destina a melhorar o desempenho e não a proteção do Dia das Bruxas, porque sua presença não é consistente.
Estou testando isso no 2016 CTP 3.1, mas vejo o mesmo comportamento no 2014 SP1 CU3.
Publiquei um script que gera esquema e dados e orienta você na demonstração do problema aqui .
A questão é principalmente por curiosidade sobre o comportamento do otimizador neste ponto, pois tenho uma solução alternativa para o problema que gerou a pergunta (um grande spool cheio de TempDB). Agora estou excluindo usando a troca de partição.
Estou usando o PostgreSQL 9.1 e quero restaurar os arquivos de backup gerados com pg_dump
:
sudo pg_dump -h 127.0.0.1 -U postgres --clean --inserts -E UTF8 -f out.sql database_name
Este comando gera um arquivo sql válido que começa com a eliminação de quaisquer objetos de banco de dados existentes, em seguida, gera todas as tabelas, indiizes, sequências e assim por diante e, finalmente, insere os dados.
Quando tento restaurar o arquivo de backup gerado com: (quebras de linha adicionadas apenas para fins de exibição)
sudo pg_restore
-d database_name -h 127.0.0.1 -U postgres
--format=c --clean --create out.sql
ele falha e imprime:
pg_restore: [archiver] did not find magic string in file header
Qual é a razão disso?