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

Charlieface's questions

Martin Hope
Charlieface
Asked: 2023-08-28 09:59:29 +0800 CST

Consulta de agregação de visualização particionada não otimizada

  • 8

Dadas as duas tabelas a seguir:

CREATE TABLE SalesLedger (
  Id int PRIMARY KEY IDENTITY,
  Date date NOT NULL,
  Total decimal(38,18),
  INDEX IX (Date, Total)
);

CREATE TABLE Purchases (
  Id int PRIMARY KEY IDENTITY,
  Date date NOT NULL,
  Total decimal(38,18),
  INDEX IX (Date, Total)
);

E a seguinte visão

CREATE VIEW ViewMetrics
AS

Select
  Date,
  'Sale' as Metric,
  Total as Value
From SalesLedger

UNION ALL

Select
  Date,
  'Purchase' as Metric,
  Total as Value
From Purchases;

A consulta a seguir usa um Concatenation Sortpar:

Select SUM(Value) as Sales, Date
from ViewMetrics
Group By Date;

insira a descrição da imagem aqui

Colar o plano


Considerando que uma pequena reescrita dá obviamente mais desempenhoMerge Concatenation

SELECT SUM(Sales), Date
FROM (
  Select SUM(Value) as Sales, Date
  from ViewMetrics
  Group By Metric, Date
) t
GROUP BY Date;

insira a descrição da imagem aqui

Colar o plano


O compilador pode ver claramente que a visualização está particionada por Metric, como mostra esta consulta, não Sorté necessário:

Select SUM(Value) as Sales, Date
from ViewMetrics
where Metric = 'Sale'
Group By Date;

insira a descrição da imagem aqui


A questão é: por que a primeira consulta força a Sort, enquanto a segunda pode usar uma mais eficiente Merge Concatenation, visto que a Metriccoluna não possui WHEREpredicado em nenhum dos casos?

O compilador não deveria ser capaz de ver que a Mergefuncionaria, visto que os índices já estão classificados Datee o particionamento está ativado Metric? Ou se não consegue ver isso, por que GROUP BY Metric, Datede repente lhe dá essa habilidade?

banco de dados<> violino

Ainda mais estranho, como descobriu @MartinSmith, se não houver dados, o compilador usará o plano melhor, embora sem uma agregação intermediária em Metric, Date. db<>fiddle Por outro lado, a mesclagem sem agregação parcial é provavelmente mais lenta do que a classificação após a agregação parcial, porque há mais linhas para mesclar. A questão é por que não é possível fazer agregação parcial e mesclar ao mesmo tempo por padrão?

Suponho que haja alguma otimização específica para uma visualização particionada quando a agregação inclui o particionamento, porque nesse caso ela usa uma concatenação e quando uma ordem é necessária, ela usa a concatenação de mesclagem, consulte db<> fiddle . Isso ajuda quando você deseja agregar ainda mais, pois os dados agora já estão classificados na ordem correta. Mas se você não fizer a agregação intermediária não tem lógica que a aplique.

sql-server
  • 1 respostas
  • 128 Views
Martin Hope
Charlieface
Asked: 2023-04-10 05:05:02 +0800 CST

Ligação de esquema com UDF escalar recursiva

  • 13

TL;DR; É um bug que o SQL Server permite que uma UDF escalar chame a si mesma recursivamente quando vinculada ao esquema, mas somente quando alterada para fazer isso usando a CREATE OR ALTERsintaxe? Ou é um bug que outras sintaxes não são permitidas?


Uma UDF escalar recursiva trivial pode ser construída da seguinte maneira

CREATE FUNCTION dbo.Try1 (@i int)
RETURNS int
AS BEGIN
  RETURN IIF(@i = 0, 0, @i + dbo.Try1(@i - 1));
END;

Contanto que isso não seja vinculado ao esquema, isso é permitido.


Vamos tentar vinculá-lo ao esquema, faremos

CREATE FUNCTION dbo.Try2 (@i int)
RETURNS int
WITH SCHEMABINDING
AS BEGIN
  RETURN IIF(@i = 0, 0, @i + dbo.Try2(@i - 1));
END;

Não.

Cannot find either column "dbo" or the user-defined function
or aggregate "dbo.Try2", or the name is ambiguous

Crie-o sem recursão e altere-o

CREATE OR ALTER FUNCTION dbo.Try3 (@i int)
RETURNS int
WITH SCHEMABINDING
AS BEGIN RETURN NULL; END;
ALTER FUNCTION dbo.Try3 (@i int)
RETURNS int
WITH SCHEMABINDING
AS BEGIN
  RETURN IIF(@i = 0, 0, @i + dbo.Try3(@i - 1));
END;

Um erro diferente desta vez:

Cannot schema bind function 'dbo.Try3' because name 'dbo.Try3' is invalid
for schema binding. Names must be in two-part format
and an object cannot reference itself.

Hmmm, an object cannot reference itselfquem inventou essa regra? Não está nos documentos.


Vamos tentar comCREATE OR ALTER

CREATE OR ALTER FUNCTION dbo.Try4 (@i int)
RETURNS int
WITH SCHEMABINDING
AS BEGIN
  RETURN IIF(@i = 0, 0, @i + dbo.Try4(@i - 1));
END;

Ainda não.


Mas se primeiro fizermos CREATE sem recursão, depois CREATE OR ALTER( não ALTER ) com recursão, funcionará

CREATE OR ALTER FUNCTION dbo.Try5 (@i int)
RETURNS int
WITH SCHEMABINDING
AS BEGIN RETURN NULL; END;
CREATE OR ALTER FUNCTION dbo.Try5 (@i int)
RETURNS int
WITH SCHEMABINDING
AS BEGIN
  RETURN IIF(@i = 0, 0, @i + dbo.Try5(@i - 1));
END;

O estranho é: isso não faz sentido, seja qual for a maneira que CREATE OR ALTERfuncione por baixo. Se ele realmente cair e recriar, por que não recebemos o primeiro erro? E se alterar, então por que esta última opção funciona?

A parte mais engraçada: se o criarmos sem vinculação de esquema primeiro, então CREATE OR ALTER WITH SCHEMABINDINGfaremos

Cannot schema bind function 'dbo.Try6'. 'dbo.Try6' is not schema bound.

O que é um absurdo total.

db<>violino

sql-server
  • 1 respostas
  • 344 Views
Martin Hope
Charlieface
Asked: 2021-11-11 15:21:48 +0800 CST

Manutenção de exibição indexada com chave estrangeira não elidida ao inserir a linha pai

  • 4

TL;DR;

Dada uma exibição indexada que tem JOINentre duas tabelas que já possuem um relacionamento de chave estrangeira junto com um WHEREpredicado na tabela pai.
Ao inserir na tabela pai da chave estrangeira, o compilador está adicionando manutenção de índice ao plano, mesmo que seja provável que não existam linhas correspondentes.

Isso é um bug ou talvez uma otimização perdida? Ou existe alguma falácia lógica ou algébrica em que estou?

Configurar

CREATE TABLE Parent (Id int identity primary key, SomeCol bit not null, OtherCol int not null);

CREATE TABLE Child (Id int identity primary key, ParentId int not null references Parent (Id) INDEX IX_Parent NONCLUSTERED);
CREATE VIEW dbo.vChild
WITH SCHEMABINDING
AS
SELECT c.Id, c.ParentId
FROM dbo.Child c
JOIN dbo.Parent p ON p.Id = c.ParentId
-- WHERE p.SomeCol = 0;  -- problem dependent on this line
CREATE UNIQUE CLUSTERED INDEX CX_vChild ON vChild (Id)

db<>fiddle com WHERE
db<>fiddle sem WHERE

Neste estágio, qualquer UPDATEcoluna que afete na visão, e qualquer DELETE, das tabelas da visão acionam, com razão, a manutenção da visão. O compilador pegará as linhas modificadas, as colocará em spool e as alimentará através das junções da visão, enviando quaisquer resultados para o índice da visão.

O mesmo pode ser dito para inserções para Child, porque uma linha Parentjá pode existir para (que se qualifica em relação a WHERE) e, portanto, a nova Childlinha pode se qualificar para a junção.

Problema

Ao inserir em Parent, é provável que a manutenção do índice não precise ser feita. Uma linha correspondente ainda não pode existir Childdevido ao relacionamento de chave estrangeira, portanto, não pode haver linhas da inserção que se qualifiquem para a exibição.

Se você executar o script a seguir, verá que nenhuma manutenção de exibição é feita.

INSERT Parent (SomeCol, OtherCol)
VALUES (0, 100);

PasteThePlan

insira a descrição da imagem aqui

Muito claramente, o compilador pode deduzir que a manutenção da visão não é necessária aqui.

No entanto, se você descomentar a linha WHERE p.SomeCol = 0na definição de exibição, de repente você obterá manutenção de exibição. Portanto, a adição de outra coluna à exibição, que não é uma coluna de junção e não possui um relacionamento de chave estrangeira, causa isso. Isso ocorre apesar da mesma lógica relacional aplicada: a inserção provavelmente ainda não se qualifica para a exibição, devido à coluna de chave estrangeira que ainda está lá.

PasteThePlan

insira a descrição da imagem aqui

Curiosamente, o compilador ainda pode reconhecer alguns casos em que a inserção não se qualificará para a exibição (e apesar desse exemplo específico ser parametrizado automaticamente).

Aqui o compilador reconhece que SomeColfalha o WHERE, e não há necessidade de fazer manutenção de índice.

INSERT Parent (SomeCol, OtherCol)
VALUES (1, 100);

PasteThePlan

insira a descrição da imagem aqui

sql-server t-sql
  • 1 respostas
  • 140 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