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

Gábor Major's questions

Martin Hope
Gábor Major
Asked: 2024-05-09 16:02:57 +0800 CST

Consulta Oracle SQL lenta mesmo com índices

  • 6

Tenho um banco de dados Oracle 19c (19.0.0.0.0) e duas tabelas com muitas colunas, mencionarei apenas as relevantes:

tabela 1:

  • data de criação
  • caractere contact_key (96 bytes)

mesa 2:

  • caractere contact_key (96 bytes)
  • csi_tfid varchar2(300 bytes)

table1 tem 210 milhões de linhas e é particionada anualmente. table2 possui 6,8 milhões de registros e não é particionada.

A consulta a seguir é executada muito rapidamente, em torno de 0,05 a 0,1 segundo:

select * from table1 m, table2 c
where
c.contact_key = m.contact_key
and c.csi_tfid = '1234567';

Mas assim que adiciono uma condição where para obter apenas os últimos registros (o que é relevante para a aplicação), a velocidade de execução cai para 1 minuto, ou até mais lenta:

select * from table1 m, table2 c
where
c.contact_key = m.contact_key
and c.csi_tfid = '1234567'
and m.createtime >= (sysdate-30);

Tentei colocar uma data codificada lá como to_date('2024-04-09', 'YYYY-MM-DD'), mesmo resultado.

Tenho índices individuais em todas as colunas desta consulta:

tabela 1:

  • ik_table1_contact_k não exclusivo
  • ik_table1_createtime não exclusivo

mesa 2:

  • ik_table2_contact_key único
  • ik_table2_csi_tfid não exclusivo

Tentei adicionar índice composto a ambas as tabelas, para incluir contact_key e createtime (para tabela1) e contact_key e csi_tfid (para tabela2), aparentemente sem efeito.

Para a consulta rápida, a Oracle gera este plano:

insira a descrição da imagem aqui

Plan hash value: 323565418
 
-----------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                   | Name                | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                            |                     |     3 |  1857 |   118   (0)| 00:00:01 |       |       |
|   1 |  NESTED LOOPS                               |                     |     3 |  1857 |   118   (0)| 00:00:01 |       |       |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED       | TABLE2              |     3 |   966 |     7   (0)| 00:00:01 |       |       |
|*  3 |    INDEX RANGE SCAN                         | IK_TABLE2_CSI_TFID  |     3 |       |     3   (0)| 00:00:01 |       |       |
|   4 |   PARTITION RANGE ALL                       |                     |     1 |   297 |    37   (0)| 00:00:01 |     1 |    12 |
|   5 |    TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| TABLE1              |     1 |   297 |    37   (0)| 00:00:01 |     1 |    12 |
|*  6 |     INDEX RANGE SCAN                        | IK_TABLE1_CONTACT_K |     1 |       |    36   (0)| 00:00:01 |     1 |    12 |
-----------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   3 - access("C"."CSI_TFID"='1234567')
   6 - access("C"."CONTACT_KEY"="M"."CONTACT_KEY")

Para a consulta lenta, com a condição createtime, é bem diferente:

insira a descrição da imagem aqui

Plan hash value: 1504517877
 
-------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                   | Name                  | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                            |                       |     2 |  1238 |    10   (0)| 00:00:01 |       |       |
|   1 |  NESTED LOOPS                               |                       |     2 |  1238 |    10   (0)| 00:00:01 |       |       |
|   2 |   PARTITION RANGE ITERATOR                  |                       |     3 |   891 |     6   (0)| 00:00:01 |   KEY |    12 |
|   3 |    TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| TABLE1                |     3 |   891 |     6   (0)| 00:00:01 |   KEY |    12 |
|*  4 |     INDEX RANGE SCAN                        | IK_TABLE1_CREATETIME  |     3 |       |     3   (0)| 00:00:01 |   KEY |    12 |
|*  5 |   TABLE ACCESS BY INDEX ROWID               | TABLE2                |     1 |   322 |     2   (0)| 00:00:01 |       |       |
|*  6 |    INDEX UNIQUE SCAN                        | IK_TABLE2_CONTACT_KEY |     1 |       |     1   (0)| 00:00:01 |       |       |
-------------------------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   4 - access("M"."CREATETIME">=SYSDATE@!-30)
   5 - filter("C"."CSI_TFID"='1234567')
   6 - access("C"."CONTACT_KEY"="M"."CONTACT_KEY")
 
Note
-----
   - this is an adaptive plan

Mostra o custo muito baixo para ambas as consultas, por isso é estranho para mim como essa única condição pode adicionar tanta complexidade.

Na tabela1, contact_key será basicamente único, não há restrição exclusiva, mas a lógica do aplicativo garante que seja único, então acho que a consulta rápida usa esta coluna para pesquisa, que será rápida. Mas a consulta lenta usa a coluna createtime para pesquisar nesta tabela, que será mais lenta, pois haverá muitos registros onde creatime é > sysdate - 30.

Tentei contornar desta forma, esperando poder fazer a consulta rápida como subconsulta e depois filtrar apenas os resultados disso:

select sq.* from (
  select * from table1 m, table2 c
  where
  c.contact_key = m.contact_key
  and c.csi_tfid = '1234567'
) sq
where sq.createtime >= (sysdate-30);

Mas recebi a mesma consulta lenta, com o mesmo plano de execução. O que mais posso tentar? O aplicativo atualmente não possui lógica para filtrar os resultados, ele depende da instrução SELECT.


-- ATUALIZAÇÃO do DBA

O DBA verificou algumas estatísticas e histórico, e parece que esta consulta começou a "comportar-se mal" por volta de 1º de maio. Antes usava outro índice, semelhante ao sugerido pelo @Andy DB Analyst (outro índice, não mencionei acima). Verifiquei todos os índices, as estatísticas, a data da última análise, etc., são quase idênticas.

oracle
  • 2 respostas
  • 37 Views
Martin Hope
Gábor Major
Asked: 2021-06-02 22:59:21 +0800 CST

Oracle 19c não pode reduzir a coluna blob

  • 0

Excluí vários dados antigos de um esquema, incluindo dados BLOB, e depois tentei reduzir e compactar tudo. Consegui reduzir todas as tabelas (habilitar movimento de linha, diminuir espaço compacto, desabilitar movimento de linha), exceto a coluna BLOB, que é armazenada em um segmento separado:

SELECT
    segment_name,
    SUM(bytes) / 1024 / 1024 / 1024 AS "GB_SIZE"
FROM
    dba_segments
WHERE
    owner = 'MY_OWNER'
GROUP BY
    segment_name
ORDER BY
    SUM(bytes) / 1024 / 1024 / 1024 DESC;

Segmento em questão:

SEGMENT_NAME                GB_SIZE
SYS_LOB0000072887C00005$$   0,35955810546875

Nota: este é um banco de dados de teste, em prod DB, isso é cerca de 660 GB.

Quando tento reduzi-lo, recebo este erro:

ALTER TABLE my_table MODIFY LOB ( my_blob ) ( SHRINK SPACE );

Error starting at line : 1 in command -
alter table my_table modify lob (my_blob) (shrink space)
Error report -
ORA-10635: Invalid segment or tablespace type
10635. 00000 -  "Invalid segment or tablespace type"
*Cause:    Cannot shrink the segment because it is not in auto segment space
           managed tablespace or it is not a data, index or lob segment.
*Action:   Check the tablespace and segment type and reissue the statement

Detalhes do segmento:

SELECT
    *
FROM
    dba_segments
WHERE
    segment_name = 'SYS_LOB0000072887C00005$$';

Detalhes relevantes:

  • Tipo de segmento: LOBSEGMENT
  • Subtipo de segmento: SECUREFILE
  • Nome do tablespace: MY_DATA

Detalhes do espaço de tabela:

SELECT
    *
FROM
    dba_tablespaces
WHERE
    tablespace_name = 'MY_DATA';

Detalhes relevantes:

  • Gerenciamento de extensão: LOCAL
  • Tipo de alocação: SISTEMA
  • Gerenciamento de espaço de segmento: AUTO

Versão exata do Oracle:

Oracle Database 19c Enterprise Edition Versão 19.0.0.0.0 - Produção

Tanto quanto eu posso dizer, tudo está como deveria ser, então não tenho certeza do que está faltando.

oracle shrink
  • 1 respostas
  • 1217 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