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 / dba / Perguntas / 278835
Accepted
Lennart - Slava Ukraini
Lennart - Slava Ukraini
Asked: 2020-10-29 14:45:35 +0800 CST2020-10-29 14:45:35 +0800 CST 2020-10-29 14:45:35 +0800 CST

Detecção de contradições

  • 772

Encontrei algumas anotações antigas minhas de 2011 e também reli o excelente artigo 10 Cool SQL Optimisations That Not Depend on the Cost Model de @lukas-eder. Então eu pensei em levar minhas notas para outra rodada. O cenário é bastante simples Fiddle

create table emp ( 
    emp_no int not null primary key, 
    title varchar(10) not null, 
    salary int not null, 
        check (emp_no > 0), 
        check (title in ('BOSS','WORK'))
);

insert into emp with recursive t (n) as (
    values (1) 
    union all 
    select n+1 from t where n+1 < 1000
) select n, case when mod(n,10) = 0 then 'BOSS' else 'WORK' end, 
            case when mod(n,10) = 0 then 110 else 0 end + mod(n,90) 
from t;

Agora, dadas as regras:

 (TITLE = BOSS) implies (SALARY > 100)

e

 (TITLE = WORK) implies (SALARY <= 100)

que pode ser implementado como:

-- (TITLE = BOSS) => (SALARY > 100)
alter table emp add constraint cc1 
    CHECK ( (title <> 'BOSS' OR salary > 100) );
-- (TITLE = WORK) => (SALARY <= 100)
alter table emp add constraint cc2
    CHECK ( (title <> 'WORK' OR salary <= 100) );

e a consulta:

select * 
from emp 
where title = 'BOSS' and salary <= 100

o DBMS pode detectar a contradição e retornar um conjunto de resultados vazio sem nem mesmo tocar nos dados?

Let A = ( title = ’BOSS’ ), B = ( salary > 100 )

select * from emp where (A ^ ~B)                    
select * from emp where (A ^ ~B) ^ (~A v B)           # by cc1 
select * from emp where (A ^ ~B ^ ~A) v (A ^ ~B ^ B)    
select * from emp where (FALSE ^ ~B) v (A ^ FALSE)      
select * from emp where (FALSE) v (FALSE)           
select * from emp where (FALSE)

Eu tentei o Postgres 13 (veja o violino acima)

Seq Scan on emp  (cost=0.00..26.50 rows=2 width=46) (actual time=0.134..0.134 rows=0 loops=1)
  Filter: ((salary <= 100) AND ((title)::text = 'BOSS'::text))
  Rows Removed by Filter: 999
Planning Time: 0.312 ms
Execution Time: 0.149 ms

e Db2 11.5.4.0:

Optimized Statement:
-------------------
SELECT 
  Q1.EMP_NO AS "EMP_NO",
  Q1.TITLE AS "TITLE",
  Q1.SALARY AS "SALARY" 
FROM 
  DB2INST1.EMP AS Q1 
WHERE 
  (Q1.SALARY <= 100) AND 
  (Q1.TITLE = 'BOSS')

Access Plan:
-----------
        Total Cost:             51.8267
        Query Degree:           1


      Rows 
     RETURN
     (   1)
      Cost 
       I/O 
       |
     90.2441 
     TBSCAN
     (   2)
     51.8267 
        4 
       |
       999 
 TABLE: DB2INST1
       EMP
       Q1

mas ambos não conseguem fazê-lo. Algum outro SGBD que possa identificar a contradição e agir sobre ela? É claro que isso é mais uma diversão do que um problema do mundo real, mas ainda assim.

Edit: A restrição sugerida por @federico-razzoli em sua resposta também não funciona:

alter table emp add constraint cc1
    check ((title = 'BOSS' and salary > 100) or 
           (title = 'WORK' AND salary <= 100));

e a mesma consulta ainda causa acesso à tabela

 Rows 
 RETURN
 (   1)
  Cost 
   I/O 
   |
 90.2441 
 TBSCAN
 (   2)
 51.8267 
    4 
   |
   999 

TABELA: DB2INST1 EMP Q1

optimization rdbms
  • 2 2 respostas
  • 122 Views

2 respostas

  • Voted
  1. Federico Razzoli
    2020-10-30T03:43:53+08:002020-10-30T03:43:53+08:00

    Sua pergunta é ótima, mas pula uma etapa. Você está assumindo que o planejador de consultas (ou otimizador, dependendo da terminologia que você preferir) pode levar em conta todos os CHECKs, mesclando-os.

    Então você tem:

    check (title in ('BOSS','WORK'))
    

    E:

    CHECK ( (title <> 'BOSS' OR salary > 100) )
    CHECK ( (title <> 'WORK' OR salary <= 100) )
    

    E você assume que o planejador deve ser capaz de saber que:

    CHECK ((title = 'BOSS' and salary > 100) or title = 'WORK' AND salary <= 100)
    

    Este pode ser o caso ou não.

    Em geral, a pergunta para sua resposta depende da tecnologia que você está usando. MySQL e MariaDB não levam em conta CHECKs. Algumas outras tecnologias provavelmente o fazem. Você terá que testar as tecnologias nas quais está interessado.

    • 1
  2. Best Answer
    Lennart - Slava Ukraini
    2020-10-31T06:26:41+08:002020-10-31T06:26:41+08:00

    Veja a seguir um resumo de como vários DBMS lidam com as restrições na questão. 3 outras consultas também são testadas:

    1.  select * 
        from emp 
        where title = 'BOSS' and salary <= 100
    
    2.  select * 
        from emp 
        where title = 'BOSS' and salary <= 100 
          and False
    
    3.  select * 
        from emp 
        where title = 'BOSS' and salary <= 100 
          and ( NOT (title = 'BOSS' AND salary <= 100) )
    
    4. select *  
       from emp 
       where title = 'BOSS' and salary <= 100 
         and ( (title <> 'BOSS' OR salary > 100) )
    

    Db2 V11.5.4.0

    Falha ao identificar a contradição em q1, é bem-sucedido para q2, q3, q4

    db2 "explain plan for select ..."
    db2exfmt -d nya -1
    [...]
    
    Access Plan:
    
    -----------
    Total Cost:             51.8267
    Query Degree:           1
    
    
      Rows 
     RETURN
     (   1)
      Cost 
       I/O 
       |
     90.2441 
     TBSCAN
     (   2)
     51.8267 
        4 
       |
       999 
    TABLE: DB2INST1
       EMP
       Q1
    

    2,3,4.

    Optimized Statement:
    -------------------
    SELECT 
      NULL AS "EMP_NO",
      NULL AS "TITLE",
      NULL AS "SALARY" 
    FROM 
      (VALUES
      ) AS Q1 
    WHERE 
      (FALSE = TRUE)
    
    Access Plan:
    -----------
        Total Cost:             7.58112e-05
        Query Degree:           1
    
    
       Rows 
      RETURN
      (   1)
       Cost 
        I/O 
        |
         0 
      TBSCAN
      (   2)
    1.27533e-05 
         0 
        |
         0 
    TABFNC: SYSIBM  
      GENROW
    

    MariaDB 10.5

    Falha ao identificar a contradição na consulta 1,3,4, é bem-sucedida na consulta 2

    Fiddle MariaDB

    1,3,4.

        Extra
        Using where
    
    1.  Extra
       Impossible WHERE
      

    MySQL 8.0

    Falha ao identificar a contradição na consulta 1,3,4, é bem-sucedida na consulta 2

    Fiddle MySQL

    1,3,4.

        Extra
        Using where
    
    1.  Extra
       Impossible WHERE
      

    Oráculo 18c

    Não tenho 100% de certeza de como interpretar o plano, mas diz TABLE ACCESS Full para todas as 4 consultas, então acho que significa que falhou 1,2,3,4

    violino Oracle 18c

    Postgres 13

    Falha ao identificar a contradição em q1, q3, q4, é bem-sucedido para q2

    1,3,4. QUERY PLAN Seq Scan on emp (custo=0.00..26.50 linhas=2 largura=46) Filtro: ( ...

    2. Resultado do PLANO DE CONSULTA (custo=0,00..0,00 linhas=0 largura=0) Filtro Único: falso

    Fiddle Postgres

    SQL Server 2019

    Falha ao identificar a contradição em q1, q3, q4, é bem-sucedido para q2

    Fiddle SQL-server

    Conclusão

    Nenhum dos DBMS testados conseguiu usar as informações das restrições.

    O Db2 é o único que usa a informação se ela for injetada na consulta.

    Ao que parece, o Oracle é o único que falha em todas as 4 consultas.

    • 0

relate perguntas

  • Como devo otimizar o armazenamento para esta tabela?

  • DBMS_REDEFINITION vs EXCHANGE PARTITION no oracle

  • Existe uma boa "regra de ouro" para traduzir o custo EXPLAIN para o tempo de execução (relógio de parede)?

  • O que significa "índice" em RDBMSs? [fechado]

  • Quais são as diferenças entre o NoSQL e um RDBMS tradicional?

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