AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-36748

Fabian Schmied's questions

Martin Hope
Fabian Schmied
Asked: 2025-03-27 18:19:32 +0800 CST

Por que o SQL Server não usaria um operador Merge Join (Concatenação) em valores não exclusivos, mas pré-classificados?

  • 8
Esta pergunta foi migrada do Stack Overflow porque pode ser respondida no Database Administrators Stack Exchange. Migrada há 15 dias .

Tenho uma consulta muito simples em que uso um UNION ALL+ ORDER BYem duas consultas que retornam dados pré-ordenados de seus respectivos índices. Por algum motivo, o SQL não usa um Merge Join (Concatenation)para isso, mas um Concatenation, seguido por um Sort. Qual poderia ser o motivo?

Aqui está um exemplo completo de reprodução. (As INDEXdicas são necessárias para que o SQL Server use o índice, apesar do baixo número de linhas na tabela.)

CREATE TABLE T1(
    SequenceNumber bigint IDENTITY NOT NULL,
    TenantId uniqueidentifier NOT NULL,
    Object1Id uniqueidentifier NOT NULL,
    Payload nvarchar(max) NOT NULL,
    OtherNumber bigint NOT NULL,

  CONSTRAINT PK_T1 PRIMARY KEY CLUSTERED (TenantId,SequenceNumber ASC)
)

CREATE INDEX IX_TenantId_Object1Id_OtherNumber ON T1(TenantId, Object1Id, OtherNumber)

CREATE TABLE T2(
    SequenceNumber bigint IDENTITY NOT NULL,
    TenantId uniqueidentifier NOT NULL,
    Object2Id uniqueidentifier NOT NULL,
    Payload nvarchar(max) NOT NULL,
    OtherNumber bigint NOT NULL,

  CONSTRAINT PK_T2 PRIMARY KEY CLUSTERED (TenantId,SequenceNumber ASC)
)

CREATE INDEX IX_TenantId_Object2Id_OtherNumber ON T2(TenantId, Object2Id, OtherNumber)

DECLARE @tenantId UNIQUEIDENTIFIER = NEWID()
DECLARE @object1Id UNIQUEIDENTIFIER = NEWID()
DECLARE @object2Id UNIQUEIDENTIFIER = NEWID()

SELECT OtherNumber, Payload FROM T1 WITH (INDEX(IX_TenantId_Object1Id_OtherNumber)) WHERE TenantId = @tenantId AND Object1Id = @object1Id
UNION ALL
SELECT OtherNumber, Payload FROM T2 WITH (INDEX(IX_TenantId_Object2Id_OtherNumber)) WHERE TenantId = @tenantId AND Object2Id = @object2Id
ORDER BY OtherNumber

DROP TABLE T1
DROP TABLE T2

E esta é uma captura de tela do plano de execução: Plano de execução da consulta acima mencionada

Quando adiciono a MERGE UNIONopção, o SQL Server pré-classifica explicitamente os resultados individuais da consulta (em OtherNumbere Payload, por algum motivo).

Agora, uma reviravolta interessante: quando adiciono uma restrição UNIQUE às OtherNumbercolunas, o SQL Server repentinamente escolhe o Merge Join (Concatenation)operador. Por quê?

Testei isso localmente no SQL Server 2016 e no Azure SQL.

sql-server
  • 1 respostas
  • 77 Views
Martin Hope
Fabian Schmied
Asked: 2016-03-29 08:50:53 +0800 CST

Posso confiar na leitura dos valores de identidade do SQL Server em ordem?

  • 28

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 Identityvalor 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 Identitycoluna 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 COMMITTEDe sem IDENTITY_INSERT). Ao mesmo tempo, existem processos que leem periodicamente as linhas do índice clusterizado, ordenadas por aquela CheckpointSequencecoluna (também em nível de isolamento READ COMMITTED, com a READ COMMITTED SNAPSHOTopçã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 CheckpointSequencecláusula ( e uma WHERE CheckpointSequence > -1clá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 Identitynão diz muito sobre como Identityfunciona 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:

  1. Uma transação é iniciada (explícita ou implicitamente).
  2. Um valor de identidade (X) é gerado.
  3. 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).
  4. A linha é inserida.
  5. 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 Identityimplementaçã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?

sql-server locking
  • 6 respostas
  • 5230 Views
Martin Hope
Fabian Schmied
Asked: 2014-04-07 23:41:24 +0800 CST

Detectando alterações em uma tabela do SQL Server

  • 16

Na minha aplicação, com um banco de dados rodando no SQL Server 2012, tenho um trabalho (tarefa agendada) que executa periodicamente uma consulta cara e grava os resultados em uma tabela que pode ser consultada posteriormente pelo aplicativo.

Idealmente, eu gostaria de executar essa consulta cara apenas se algo mudou desde que a consulta foi executada pela última vez. Como as tabelas de origem são muito grandes, não posso simplesmente selecionar uma soma de verificação sobre todas as colunas candidatas ou algo assim.

Tenho as seguintes ideias:

  • Escreva explicitamente um carimbo de data/hora da última alteração, um sinalizador "deve haver consultas" ou algo assim em uma tabela de rastreamento sempre que eu alterar algo em uma tabela de origem.
  • Use um gatilho para fazer o mesmo.

No entanto, eu realmente gostaria de saber se existe uma maneira leve de detectar alterações em uma tabela sem que eu rastreie explicitamente as gravações. Posso, por exemplo, pegar o "atual" ROWVERSIONde uma tabela ou algo assim?

sql-server sql-server-2012
  • 5 respostas
  • 87787 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve