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-10044

Dai's questions

Martin Hope
Dai
Asked: 2021-08-24 13:31:53 +0800 CST

Como posso suprimir ou desabilitar a inserção de histórico de tabela temporal para uma única instrução ou transação?

  • 0

Eu tenho uma tabela que armazena informações do cliente (seu material de CRM padrão do pântano):

CREATE TABLE dbo.Customers (
    TenantId    int            NOT NULL,
    CustomerId  int            NOT NULL,
    
    FirstName   nvarchar(50)   NOT NULL DEFAULT '',
    LastName    nvarchar(50)   NOT NULL DEFAULT '',
    CompanyName nvarchar(50)   NOT NULL DEFAULT '',

    Notes       nvarchar(4000) NOT NULL DEFAULT ''
)

Esta tabela foi recentemente convertida em uma tabela temporal do SQL Server:

ALTER TABLE dbo.Customers
    ADD COLUMN
        SysStart datetime2(7) GENERATED ALWAYS AS ROW START NOT NULL,
        SysEnd   datetime2(7) GENERATED ALWAYS AS ROW END   NOT NULL;

GO

ALTER TABLE dbo.Customers WITH (
    PERIOD FOR SYSTEM_TIME ( SysStart, SysEnd ),
    SYSTEM_VERSIONING = ON ( HISTORY_TABLE = dbo.Customers_History )
)

Desde que isso aconteceu, um problema surgiu: o formulário voltado para o usuário que os usuários editam os detalhes do cliente salva automaticamente o conteúdo do formulário 2 segundos após o último pressionamento de tecla, e cada salvamento resulta em uma UPDATEinstrução com quantidades de dados cada vez maiores - e assim SQL Server está constantemente adicionando novas linhas à Customers_Historytabela, com 2 segundos de intervalo, o que resulta em linhas com poucas informações e spam.

Então é isso que eu vejo quando faço um SELECT * FROM dbo.Customers_History WHERE CustomerId = 123, por exemplo:

insira a descrição da imagem aqui

Eu estava pensando que o código do lado do servidor que lida com os envios de salvamento automático poderia verificar se o estado do formulário de entrada é uma alteração incremental e, em caso afirmativo, UPDATEa dbo.Customerstabela sem adicionar nenhuma linha à Customers_Historytabela.

Até agora, a única maneira que vejo para fazer isso é definindoSYSTEM_VERSIONING = OFF dentro de uma transação, no entanto, tenho algumas dúvidas antes de realmente implementar isso ...

  1. Embora a documentação diga (até recomende) a execução ALTER TABLE dbo.Customers SET (SYSTEM_VERSIONING = OFF);dentro de uma transação, ela não diz como isso afetaria outros usuários e conexões simultâneos . Afinal, esta é uma instrução DML, e as instruções DML têm comportamento inconsistente (hah!) com isolamento.

  2. Iniciar e concluir uma transação em um PROCEDURElote armazenado ou SQL é uma coisa - mas determinar se um UPDATEé realmente incremental ou não pode exigir alguma lógica de código de aplicativo personalizado, o que significa ter que iniciar e confirmar a transação a partir do código de aplicativo, o que parece uma má ideia por causa das milhares de coisas que agora podem dar errado , sem falar nos problemas de desempenho (neste caso, a latência da rede do servidor de aplicativos para o servidor de banco de dados deve ser inferior a 1 ms, mas isso ainda afetará a escalabilidade ).


Supondo que eu possa fazer isso em um PROCEDURE, este código abaixo está correto e ele será dimensionado?

CREATE PROCEDURE dbo.UpdateSingleCustomerRow(
    @tenantId    int,
    @customerId  int,
    @firstName   nvarchar(50),
    @lastName    nvarchar(50),
    @companyName nvarchar(50),
    @notes       nvarchar(4000)
)

BEGIN TRY

    BEGIN TRANSACTION editCustomerTxn;

    SET XACT_ABORT ON;

    -- Is it an incremental change?
    DECLARE @isIncremental bit = 0;

    IF EXISTS( SELECT 1 FROM dbo.Customers WHERE
        CustomerId = @customerId
        AND
        TenantId = @tenantId
        AND
        CHARINDEX( FirstName, @firstName ) > 0
        AND
        CHARINDEX( LastName, @lastName ) > 0
        AND
        CHARINDEX( CompanyName, @companyName ) > 0
        AND
        CHARINDEX( Notes, @notes ) > 0
    )
    BEGIN
        SET @isIncremental = 1;
    END

    -----------------------

    IF @isIncremental = 1
    BEGIN
        ALTER TABLE dbo.Customers SET ( SYSTEM_VERSIONING = OFF );
    END

    UPDATE
        dbo.Customers
    SET
        FirstName   = @firstName,
        LastName    = @lastName,
        CompanyName = @companyName,
        Notes       = @notes
    WHERE
        CustomerId = @customerId
        AND
        TenantId = @tenantId;
    
    IF @isIncremental = 1
    BEGIN
        ALTER TABLE dbo.Customers SET (
            SYSTEM_VERSIONING = ON(
                HISTORY_TABLE = dbo.Customers_History
            )
        );
    END
    
    COMMIT TRANSACTION editCustomerTxn;

    RETURN 0;

END TRY
BEGIN CATCH
    
    IF @@TRANCOUNT > 0
    BEGIN
        ROLLBACK TRANSACTION editCustomerTxn;
    END
    
    RETURN 1;

END CATCH

... mas isso não parece certo para mim - porque isso é basicamente a mesma coisa que hackear restrições adiáveis ​​com ALTER TABLE dbo.Customers NOCHECK CONSTRAINT ALL.

sql-server azure-sql-database
  • 2 respostas
  • 256 Views
Martin Hope
Dai
Asked: 2021-06-24 04:38:40 +0800 CST

Como posso alterar o sinalizador "auto_created" do Azure SQL INDEX de 1 para 0? (Ele entra em conflito com SSDT)

  • 1

Estou enfrentando um problema de longa data em que o SSDT pensará que um índice de tabela no meu banco de dados SQL do Azure não existe, quando na verdade existe.

Após as últimas horas pesquisando os rastreamentos do XEvent e percorrendo a desmontagem do SSDT, descobri que o motivo é porque o SSDT procura índices com essa consulta (repetida abaixo para googleabilidade).

A consulta tem o predicado [i].[auto_created] = 0.

Quero manter o índice em vez de recriá-lo - existe alguma maneira de definir sys.indexes.auto_created = 0um índice específico de alguma forma?


ATUALIZAÇÃO: Acabei de encontrar este tópico, parece que não estou sozinho , mas também não devo esperar nenhuma alteração no SSDT, * grumble *


UPDATE2: Curiosamente, usar WITH AUTO_CREATED = ON é uma opção válida para o CREATE INDEXSQL do Azure , mas não para ALTER INDEX, *mais resmungando* : quando tentei, recebi este erro:

ALTER INDEX IX_StarTrekTngBestMoments ON dbo.GeneRoddenberryFanClub SET ( AUTO_CREATED = OFF );

Msg 155, Nível 15, Estado 1, Linha 1

'AUTO_CREATED' não é uma opção ALTER INDEX reconhecida.


História para os curiosos:

  • Cerca de 2-3 anos atrás, o Azure SQL Performance Analyzer criou automaticamente um índice em uma das minhas tabelas.
    • O tipo de índices com um nome como nci_wi_TableName_ABCDEF....
  • Quando o Azure SQL Performance Analyzer cria um índice, exibição ou outro objeto, ele define o auto_createdsinalizador como 1.
  • As ferramentas de design do SQL Server do Visual Studio (SSDT, também conhecido como *.sqlproj) sempre excluem objetos com auto_created <> 0, o que significa que o SSDT não viu meu índice.
  • Você pensaria que isso não seria um problema porque o índice não estava no meu projeto em primeiro lugar, então não há conflito, certo?
    • Bem, não - na época eu usei SSMS, não SSDT, para copiar a INDEXdefinição de 's no meu projeto SSDT - usando o menu "Script index as CREATE to..." e copiando + colando o SQL no meu arquivo de tabela SSDT . E desde então tenho tido conflitos com SSDT versus meu banco de dados SQL do Azure - sem ter problemas com minhas versões de desenvolvimento local e local porque o SSDT as criou sem o auto_createdsinalizador.
  • Enviei um tíquete de suporte ao suporte do Azure sobre isso em janeiro de 2021 - a solicitação de suporte foi muito lenta, mas em março de 2021 eles me disseram que "enviarão o plano de ação em breve" (o que quer que isso signifique), mas eu não ouvi qualquer coisa desde... Vergonha , Microsoft, Vergonha .

Eu esperava que houvesse uma opção no SSDT para não ignorar auto_createdobjetos, mas infelizmente a consulta SQL que ele usa para enumerar índices no banco de dados tem o termo predicado codificado:

insira a descrição da imagem aqui

SELECT * FROM (
SELECT * FROM (
SELECT DISTINCT
    SCHEMA_NAME([o].[schema_id]) AS [SchemaName]
   ,[i].[object_id]        AS [ColumnSourceId]
   ,[o].[name]             AS [ColumnSourceName]
   ,[o].[type]             AS [ColumnSourceType]
   ,[i].[index_id]         AS [IndexId]
   ,[i].[name]             AS [IndexName]
   ,[f].[type]             AS [DataspaceType]
   ,[f].[data_space_id]    AS [DataspaceId]
   ,[f].[name]             AS [DataspaceName]
   ,CASE WHEN exists(SELECT 1 FROM [sys].[columns] AS [c] WITH (NOLOCK) WHERE [c].[object_id] = [o].[object_id] AND  [c].[is_filestream] = 1) THEN
            [ds].[data_space_id]
        ELSE
            NULL
        END  AS [FileStreamId]
   ,[ds].[name]            AS [FileStreamName]
   ,[ds].[type]            AS [FileStreamType]   
   ,[i].[fill_factor]      AS [FillFactor]    
   ,CONVERT(bit, CASE [i].[type] WHEN 1 THEN 1 WHEN 5 THEN 1 ELSE 0 END) 
                           AS [IsClustered]
   ,[i].[is_unique]        AS [IsUnique]
   ,[i].[is_padded]        AS [IsPadded]
   ,[i].[ignore_dup_key]   AS [DoIgnoreDuplicateKey]
   ,[t].[no_recompute]     AS [NoRecomputeStatistics]
   ,[t].[is_incremental]   AS [DoIncrementalStatistics]
   ,[i].[allow_row_locks]  AS [DoAllowRowLocks]
   ,[i].[allow_page_locks] AS [DoAllowPageLocks]
   ,[i].[is_disabled]      AS [IsDisabled]
   ,[i].[filter_definition]
                           AS [Predicate]
   ,[i].[compression_delay] AS [CompressionDelay]
   ,CONVERT(bit, ISNULL(INDEXPROPERTY([i].[object_id], [i].[name], N'IsOptimizedForSequentialKey'), 0)) AS [DoOptimizeForSequentialKey]
   ,CONVERT(bit, CASE WHEN [ti].[data_space_id] <> [i].[data_space_id] THEN 0 ELSE 1 END)
                           AS [EqualsParentDataSpace]
   ,[i].[type]             AS [IndexType]
   ,[i].[auto_created]     AS [AutoCreated]
  ,CONVERT(BIT, CASE WHEN [hi].[object_id] IS NULL THEN 0 ELSE 1 END) AS [IsHash]
   ,[hi].[bucket_count] AS [BucketCount]
FROM 
    [sys].[indexes] AS [i] WITH (NOLOCK)
    INNER JOIN [sys].[objects]           AS [o]  WITH (NOLOCK) ON [i].[object_id] = [o].[object_id]
    LEFT  JOIN [sys].[data_spaces]       AS [f]  WITH (NOLOCK) ON [i].[data_space_id] = [f].[data_space_id]
    LEFT  JOIN [sys].[stats]             AS [t]  WITH (NOLOCK) ON [t].[object_id] = [i].[object_id] AND [t].[name] = [i].[name]
    LEFT  JOIN [sys].[tables]            AS [ta] WITH (NOLOCK) ON [ta].[object_id] = [i].[object_id]
    LEFT  JOIN [sys].[data_spaces]       AS [ds] WITH (NOLOCK) ON [ds].[data_space_id] = [ta].[filestream_data_space_id]
    LEFT  JOIN (SELECT * FROM [sys].[indexes] WITH (NOLOCK) WHERE [index_id] < 2) AS [ti] ON [o].[object_id] = [ti].[object_id]
    LEFT OUTER JOIN [sys].[hash_indexes] AS [hi] WITH (NOLOCK) ON [hi].[object_id] = [i].[object_id] AND [hi].[index_id] = [i].[index_id]
WHERE 
    ([o].[type] = N'U' OR [o].[type] = N'V')
    AND [i].[is_primary_key] = 0
    AND [i].[is_unique_constraint] = 0
    AND [i].[is_hypothetical] = 0
    AND [i].[name] IS NOT NULL
    AND [i].[auto_created] = 0
    AND ([o].[is_ms_shipped] = 0 AND NOT EXISTS (SELECT *
                                        FROM [sys].[extended_properties]
                                        WHERE     [major_id] = [o].[object_id]
                                              AND [minor_id] = 0
                                              AND [class] = 1
                                              AND [name] = N'microsoft_database_tools_support'
                                       ))) indexBase
WHERE [IndexType] NOT IN (3, 4, 5, 6)
) AS [_results] ORDER BY ColumnSourceId,IndexId  OPTION (USE HINT('FORCE_LEGACY_CARDINALITY_ESTIMATION'));
sql-server azure-sql-database
  • 1 respostas
  • 95 Views
Martin Hope
Dai
Asked: 2020-10-05 00:35:04 +0800 CST

O SQL Server ignora STATISTICS para colunas varchar como este artigo sugere?

  • 6

(Não acredito que esta pergunta seja uma duplicata desta pergunta de 8 anos atrás , pois não estou perguntando sobre as vantagens de colunas superdimensionadas, estou perguntando sobre o comportamento demonstrado no artigo vinculado abaixo.)

Este artigo recente (2017) do SQLPerformance.com demonstra como a variação do comprimento máximo nde uma varchar(n)coluna afeta as estimativas de tamanho de linha do plano de consulta e as estimativas de tamanho do buffer de classificação que podem levar a avisos de desempenho e alocação de memória abaixo da média.

Nele, o autor afirma (grifo meu):

A partir daqui, vemos que, quanto maior a definição da coluna, maior a linha estimada e o tamanho dos dados . Nesta consulta simples, o custo de E/S (0,0512731) é o mesmo em todas as consultas, independentemente da definição, porque a varredura de índice clusterizado precisa ler todos os dados de qualquer maneira.

Mas há outros cenários em que essa linha estimada e o tamanho total dos dados terão impacto: operações que exigem recursos adicionais, como classificações.

Quando li essa afirmação (em negrito), fiquei surpreso porque pensei que o SQL Server obteria estimativas de tamanho de linha bastante precisas de seus STATISTICSobjetos de amostra mantidos nessas mesmas tabelas. Especialmente tendo em conta a SELECT AVG(LEN(email))consulta no artigo mostra que nenhuma coluna tem um valor superior a 77 caracteres.

O artigo também executa explicitamente um ALTER INDEX ALL ON dbo.Table REBUILD– que esta postagem do DB.SE diz que também será atualizado automaticamenteSTATISTICS .

(embora eu esteja surpreso que a palavra "estatísticas" não apareça em nenhum lugar no artigo SQLPerformance - então talvez no caso do autor as estatísticas não tenham sido atualizadas devido a alguma configuração da máquina e eles não notaram ?)

O SQL Server usa apenas o varcharlimite de comprimento de coluna para estimativas de tamanho de linha? Se não, por que o artigo SQLPerformance descreve o mesmo?

sql-server
  • 1 respostas
  • 541 Views
Martin Hope
Dai
Asked: 2018-01-26 17:35:21 +0800 CST

Algum dialeto SQL permite a sequência lógica de cláusulas SELECT?

  • 8

SELECTno padrão ISO/IEC SQL prescreve a seguinte ordem sintática para as subcláusulas:

SELECT
    projection-expressions
FROM
    sources
WHERE
    predicate-expression
GROUP BY
    key-expression
HAVING
    predicate-expression
ORDER BY
    ordering-expressions

Enquanto a ordem lógica de execução é esta:

FROM
    sources
WHERE
    predicate-expression
GROUP BY
    value-expression
HAVING
    value-expression
SELECT
    projection-expressions
ORDER BY
    ordering-expressions

Para usuários iniciantes de SQL, torna-se surpreendente que uma projeção definida na SELECTcláusula não esteja disponível nas cláusulas WHEREou GROUP BYmesmo que seja declarada primeiro - dado que os programas de computador geralmente seguem a ordem de execução de cima para baixo.

Também é surpreendente que os autores de SQL sejam obrigados a repetir suas expressões em cláusulas SELECT, WHEREe de GROUP BYforma redundante ou usar uma subconsulta que não se presta a uma consulta sucinta. Pelo menos quando o usuário está familiarizado com a ordem real de execução da cláusula, ele sabe por que precisa se repetir, mas isso não impede que seja frustrante.

Este problema e outros problemas relacionados estão documentados neste artigo que encontrei: https://blog.jooq.org/a-beginners-guide-to-the-true-order-of-sql-operations/ e não é surpresa que um controle de qualidade no StackOverflow tem quase 30.000 visualizações: https://stackoverflow.com/questions/3241352/using-an-alias-column-in-the-where-clause-in-postgresql

Isso me fez pensar se alguma implementação de SQL permite essa ordenação mais "lógica" de cláusulas. Observo que o Linq no .NET realmente segue essa ordem, embora eu não o descreva como sendo uma implementação SQL verdadeira, mas, de fato, no Linq o equivalente seria:

source // FROM equivalent
    .Where( predicate-expression )
    .GroupBy( key-expression )
    .Where( predicate-expression ) // HAVING equivalent
    .Select( projection-expression )
    .OrderBy( ordering-expression )

(Também gosto de como o Linq permite adicionar uma Select()projeção em qualquer lugar na sequência de comandos para que você possa usar suas expressões avaliadas sem precisar invocar expressões novamente).

Então, alguma implementação de SQL permite que você expresse consultas em uma estrutura mais lógica?

syntax
  • 1 respostas
  • 595 Views
Martin Hope
Dai
Asked: 2012-07-11 16:37:00 +0800 CST

SQL Server 2012 - SELECT e UPDATE frequentes na coluna de bits. Índice não ajuda

  • 3

Eu tenho uma tabela SQL Server com cerca de 2 milhões de linhas, esta tabela armazena documentos textuais curtos. Aqui está o meu esquema:

CREATE TABLE Documents (
    documentId bigint IDENTITY NOT NULL,
    content nvarchar(MAX) NOT NULL,
    isIndexed bit NOT NULL
)

Eu tenho um processo indexador baseado em Lucene separado que faz isso:

SELECT TOP 1 documentId, content FROM Documents WHERE isIndexed = 0

Em seguida, ele executa a operação de indexação antes de executar isto:

UPDATE Documents SET isIndexed = 1 WHERE documentId = @documentId

Inicialmente, isso funcionou bem. Quando todos os documentos na tabela não foram indexados (ou seja, todos os isIndexedvalores eram 0), cada recuperação demorava cerca de 5 ms.

No entanto, à medida que mais e mais documentos foram indexados, o tempo de recuperação aumentou lentamente. Atualmente é cerca de 150ms - uma redução de velocidade de 30 vezes. Observo que a instrução UPDATE sempre parece ser executada em menos de 2 ms, então sei que isso não é um problema.

Desde o início, a tabela sempre teve um índice não clusterizado na coluna isIndexed, mas o plano de execução real mostra que o SQL Server usa uma varredura de índice (em vez de uma busca).

O que posso fazer para acelerar o sistema?

Estou ciente de que a coluna "isIndexed" existente é ruim por si só, mas devido ao funcionamento do indexador, ele não pode solicitar documentos diretamente pelo documentId. Por esta e outras razões, não posso aceitar respostas que não resolvam o problema imediato em questão.

sql-server performance
  • 2 respostas
  • 1486 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