Проблемы производительности только в производственной базе данных - PullRequest
1 голос
/ 08 сентября 2010

У меня проблемы с производительностью при запросе таблицы в производственной базе данных.В то время как запрос выполняется в тестовой базе данных за 2,1 секунды (возвращая 8640 из 28 миллионов записей), при производстве он занимает 2,05 минуты (возвращая 8640 из 31 миллиона записей).Мне трудно найти проблему, потому что я не эксперт по оракулам.Поскольку план объяснения в обеих базах данных показывает правильное использование индексов, я склонен думать, что проблема заключается в создании таблицы / индексов.Я заметил некоторые небольшие различия между сценариями SQL, используемыми для создания таблицы:

Тестовая база данных:

create table TB_PONTO_ENE
(
  cd_ponto          NUMBER(10) not null,
  cd_fonte          NUMBER(10),
  cd_medidor        NUMBER(10),
  cd_usuario        NUMBER(10),
  dt_hr_insercao    DATE,
  dt_hr_instante    DATE not null,
  dt_hr_hora        DATE,
  dt_hr_dia         DATE,
  dt_hr_mes         DATE,
  dt_hr_instante_hv DATE,
  dt_hr_hora_hv     DATE,
  dt_hr_dia_hv      DATE,
  dt_hr_mes_hv      DATE,
  vl_eneat_del      FLOAT,
  vl_eneat_rec      FLOAT,
  vl_enere_del      FLOAT,
  vl_enere_rec      FLOAT,
  vl_eneat_del_cp   FLOAT,
  vl_eneat_rec_cp   FLOAT,
  vl_enere_del_cp   FLOAT,
  vl_enere_rec_cp   FLOAT
)
tablespace TELEMEDICAO
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  );

alter table TB_PONTO_ENE
  add constraint CP_TB_PONTO_ENE primary key (CD_PONTO, DT_HR_INSTANTE)
  using index 
  tablespace TELEMEDICAO
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  );
alter table TB_PONTO_ENE
  add constraint CE_PENE_CD_FONTE foreign key (CD_FONTE)
  references TB_FONTE (CD_FONTE) on delete set null;
alter table TB_PONTO_ENE
  add constraint CE_PENE_CD_MEDIDOR foreign key (CD_MEDIDOR)
  references TB_MEDIDOR (CD_MEDIDOR) on delete set null;
alter table TB_PONTO_ENE
  add constraint CE_PENE_CD_PONTO foreign key (CD_PONTO)
  references TB_PONTO (CD_PONTO) on delete cascade;
alter table TB_PONTO_ENE
  add constraint CE_PENE_CD_USUARIO foreign key (CD_USUARIO)
  references TB_USUARIO (CD_USUARIO) on delete set null
  disable;

Производственная база данных:

create table TB_PONTO_ENE
(
  cd_ponto          NUMBER(10) not null,
  cd_fonte          NUMBER(10),
  cd_medidor        NUMBER(10),
  cd_usuario        NUMBER(10),
  dt_hr_insercao    DATE,
  dt_hr_instante    DATE not null,
  dt_hr_hora        DATE,
  dt_hr_dia         DATE,
  dt_hr_mes         DATE,
  dt_hr_instante_hv DATE,
  dt_hr_hora_hv     DATE,
  dt_hr_dia_hv      DATE,
  dt_hr_mes_hv      DATE,
  vl_eneat_del      FLOAT,
  vl_eneat_rec      FLOAT,
  vl_enere_del      FLOAT,
  vl_enere_rec      FLOAT,
  vl_eneat_del_cp   FLOAT,
  vl_eneat_rec_cp   FLOAT,
  vl_enere_del_cp   FLOAT,
  vl_enere_rec_cp   FLOAT
)
tablespace TELEMEDICAO
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    next 5M
    minextents 1
    maxextents unlimited
    pctincrease 0
  );

alter table TB_PONTO_ENE
  add constraint CP_TB_PONTO_ENE primary key (CD_PONTO, DT_HR_INSTANTE)
  using index 
  tablespace MEDICAO_NDX
  pctfree 10
  initrans 2
  maxtrans 255
  storage
  (
    initial 64K
    next 1M
    minextents 1
    maxextents unlimited
    pctincrease 0
  );
alter table TB_PONTO_ENE
  add constraint CE_PENE_CD_FONTE foreign key (CD_FONTE)
  references TB_FONTE (CD_FONTE) on delete set null;
alter table TB_PONTO_ENE
  add constraint CE_PENE_CD_MEDIDOR foreign key (CD_MEDIDOR)
  references TB_MEDIDOR (CD_MEDIDOR) on delete set null;
alter table TB_PONTO_ENE
  add constraint CE_PENE_CD_PONTO foreign key (CD_PONTO)
  references TB_PONTO (CD_PONTO) on delete cascade;
alter table TB_PONTO_ENE
  add constraint CE_PENE_CD_USUARIO foreign key (CD_USUARIO)
  references TB_USUARIO (CD_USUARIO) on delete set null;

Производственная база данныхпомещает индексы в другое табличное пространство.Другим отличием является next 5M в объявлении табличного пространства (значение не определено в тестовой базе данных).

При просмотре свойств индекса я также вижу некоторые различия:

Тестовая база данных:

  • AVG_DATA_BLOCKS_PER_KEY 1
  • AVG_LEAF_BLOCKS_PER_KEY 1
  • BLEVEL 2
  • BUFFER_POOL ПО УМОЛЧАНИЮ
  • CLUSTERING_FACTOR 611494
  • СЖАТИЕ ОТКЛЮЧЕНО
  • Градус 1
  • DISTINCT_KEYS 28568389
  • УДАЛЕН NO
  • GENERATED N
  • GLOBAL_STATS YES
  • INDEX_NAME CP_TB_PONTO_ENE
  • INDEX_TYPE NORMAL
  • INITIAL_EXTENT 65536
  • INI_TRANS 2
  • INSTANCES 1
  • IOT_REDUNDANT_PKEY_ELIM NO
  • JOIN_INDEX NO
  • LAST_ANALYZED 21/07/2010 22:08:34
  • LEAF_BLOCKS 85809
  • LOGGING YES
  • MAX_EXTENTS 2147483645
  • MAX_TRANS 255
  • MIN_EXTENTS 1
  • NUM_ROWS 28568389
  • PARTITIONED NO
  • PCT_FREE 10
  • SAMPLE_SIZE 377209
  • SECONDARY N
  • STATUS VALID
  • TABLESPACE_NAME TELEMEDICAO
  • TABLE_NAME TB_PONTO_ENE
  • TABLE_TYPE TABLE
  • TEMPORARY N
  • UNIQUENESS UNIQUE
  • USER_STATS NO

Производственная база данных:

  • AVG_DATA_BLOCKS_PER_KEY 1
  • AVG_LEAF_BLOCKS_PER_KEY 1
  • BLEVEL 2
  • BUFFER_POOL DEFAULT
  • CLUSTERING_FACTOR 10154395
  • СЖАТИЕ ОТКЛЮЧЕНО
  • СТЕПЕНЬ 1
  • DISTINCT_KEYS 14004395
  • СОЗДАН N
  • GLOBAL_STATS ДА
  • INDEX_NAME CP_TB_PONTO_ENE
  • INDEX_TYPE НОРМАЛЬНЫЙ
  • INITIAL_EXTENT 65536
  • INI_TRANS 2
  • INSTANCEES 1
  • JOIN_INDEX NO
  • LAST_ANALYZED 05/03/2010 08:45:19
  • LEAF_BLOCKS 42865
  • Регистрация ДА
  • MAX_EXTENTS 2147483645
  • MAX_TRANS 255
  • MIN_EXTENTS 1
  • NEXT_EXTENT 1048576
  • NUM_ROWS 14004395
  • PARTITIONED NO
  • PCT_FREE 10
  • PCT_INCREASE 0
  • SAMPLE_РАЗМЕР 2800879
  • ВТОРИЧНЫЙ N
  • STATUS VALID
  • TABLESPACE_NAME MEDICAO_NDX
  • TABLE_NAME TB_PONTO_ENE
  • TABLE_TYPE TABLE
  • ВРЕМЕННЫЙ N
  • УНИКАЛЬНОСТЬ УНИКАЛЬНО
  • USER_STATS NO

Два других момента привлекли мое внимание: план объяснения для select count(*) from thetable показывает, что индекс используется в тестовой базе данных, но показывает полное сканирование таблицы в рабочей базе данных. Это привело меня к другому наблюдению: индекс тестовой базы данных имеет 160 МБ, а производственная база данных имеет более 1 ГБ (и мы не удаляем эту таблицу). Кто-нибудь может указать мне на решение?

UPDATE

Вот планы выполнения:

Тестовая база данных:

Execution Plan
----------------------------------------------------------
Plan hash value: 1441290166

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

| Id  | Operation             | Name                | Rows  | Cost (%CPU)| Time |

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

|   0 | SELECT STATEMENT      |                     |     1 | 18767   (4)| 00:03:46 |

|   1 |  SORT AGGREGATE       |                     |     1 |            |          |

|   2 |   INDEX FAST FULL SCAN| IDX_HV_TB_PONTO_ENE |    28M| 18767   (4)| 00:03:46 |

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



Statistics
----------------------------------------------------------
        111  recursive calls
          0  db block gets
      83586  consistent gets
      83533  physical reads
          0  redo size
        422  bytes sent via SQL*Net to client
        399  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
          1  rows processed

Производственная база данных

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=RULE
   1    0   SORT (AGGREGATE)
   2    1     TABLE ACCESS (FULL) OF 'TB_PONTO_ENE'




Statistics
----------------------------------------------------------
          1  recursive calls
          3  db block gets
     605327  consistent gets
     603698  physical reads
        180  redo size
        201  bytes sent via SQL*Net to client
        242  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

ОБНОВЛЕНИЕ 2

Рабочий сервер работает под управлением Oracle 9.2.0.

ОБНОВЛЕНИЕ 3

Вот статистика для выполнения с режимом оптимизатора, установленным на CHOOSE:

SQL> SELECT dt_hr_instante, vl_eneat_del,vl_eneat_rec,vl_enere_del, vl_enere_rec  FROM tb_ponto_ene WHERE cd_ponto = 31 AND dt_hr_instante BETWEEN to_date('01/06/2010 00:05:00','dd/mm/yyyy hh24:mi:ss') AND  to_date('01/07/2010 00:00:00', 'dd/mm/yyyy hh24:mi:ss');

8640 rows selected.

Elapsed: 00:01:49.51

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=1 Bytes=36)
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TB_PONTO_ENE' (Cost=4 Card=1 Bytes=36)
   2    1     INDEX (RANGE SCAN) OF 'CP_TB_PONTO_ENE' (UNIQUE) (Cost=3 Card=1)




Statistics
----------------------------------------------------------
        119  recursive calls
          0  db block gets
       9169  consistent gets
       7438  physical reads
          0  redo size
     308524  bytes sent via SQL*Net to client
       4267  bytes received via SQL*Net from client
        577  SQL*Net roundtrips to/from client
          6  sorts (memory)
          0  sorts (disk)
       8640  rows processed

Ответы [ 2 ]

2 голосов
/ 09 сентября 2010

Свойства индексов тестовой базы данных включают столбцы IOT_REDUNDANT_PKEY_ELIM и DROPPED, но не производственные индексы. Эти колонки были добавлены в оракула 10 г.

Возможно, рабочая база данных работает под старой версией 9i, а тестовая база данных под 10g? Если это так, я бы посчитал это более существенной разницей, чем что-либо еще.

Тем не менее, если "select count(*) from thetable" не использует индекс первичного ключа, это очень странно. Статистика индекса очень устарела (14 004 395 строк, если предположить, что их более 30 миллионов, и последний раз собирался в марте). Если за последние шесть месяцев таблица увеличилась в два раза, а ее статистика еще старше, это может быть проблемой.

0 голосов
/ 10 сентября 2010

План автоматического отслеживания производства говорит оптимизатор "ПРАВИЛО".Если вы посмотрите на раздел Oracle Tuning document (9i) RBO Path 15: полное сканирование таблицы, то ясно, что будет использовано полное сканирование таблицы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...