У меня есть пустая таблица, которая ранее имела большую сумму строк.
Таблица имеет приблизительно 10 столбцов и индексирует на многих из них, а также индексирует на нескольких столбцах.
DELETE FROM item WHERE 1=1
Это занимает приблизительно 40 секунд для завершения
SELECT * FROM item
это занимает 4 секунды.
План выполнения ВЫБОРА * ОТ ОБЪЕКТА показывает следующее;
SQL> select * from midas_item;
no rows selected
Elapsed: 00:00:04.29
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=19 Card=123 Bytes=73
80)
1 0 TABLE ACCESS (FULL) OF 'MIDAS_ITEM' (Cost=19 Card=123 Byte
s=7380)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
5263 consistent gets
5252 physical reads
0 redo size
1030 bytes sent via SQL*Net to client
372 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
любая идея, почему они заняли бы много времени и как зафиксировать ее, будет значительно цениться!!
Select просто выполняет полное сканирование таблицы. С другой стороны, удаление (в Oracle) должно будет хранить все удаленные строки в сегментах отката, чтобы вы могли отменить изменения позже (так что это может быть медленнее даже, чем вставка).
Вы можете найти очень длинное и полезное обсуждение, связанное с этим, на форуме Ask Tom. В зависимости от вашего бизнес-кейса, возможно, вы сможете применить больше техник.
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2345591157689
Если ваша таблица ранее была заполнена большим объемом данных, Oracle просканирует ее до максимальной отметки, даже если в ней нет данных СЕЙЧАС. Вы можете использовать инструкцию TRUNCATE для сброса HWM.
Одна из возможностей - это блокировка. То есть в таблице была строка, которая была зафиксирована и заблокирована другим удалением. Ваше удаление сидело и ждало на замке. Когда транзакция блокировки была зафиксирована, ваше удаление могло быть завершено.
Вторая возможность состоит в том, что вы сначала выполнили операцию удаления, которая извлекла блоки с диска в кэш (что потребовало времени). Когда выбор выполнялся, данные находились в кеше и поэтому выполнялись быстрее. Я думаю, что это менее вероятно, поскольку вы выбираете статистику с указанием «5252 физических чтения», поэтому они не были получены из кеша SGA. Вполне возможно, что был задействован дисковый кеш.
Третья возможность состоит в том, что существует триггер BEFORE / AFTER DELETE (не FOR EACH ROW), который что-то сделал.
Четвертая возможность состоит в том, что команда DELETE вызвала отложенную очистку блока. Когда строки были фактически удалены, если они были записаны на диск до фиксации, у них все еще была бы информация о блокировке / транзакции. Приходит ваше удаление, читает блоки, видит уже устаревшую информацию о транзакции, удаляет ее и перезаписывает блок.
Пятая возможность - это раздор. Может быть, одновременно с удалением происходило что-то еще.
Множество возможностей. Если вы можете воспроизвести это, сделайте трассировку с событиями ожидания и прогоните через TKPROF.
Если у вас много индексов в таблице, то удаление займет время, потому что каждая запись в индексе также требует удаления. Индексы ускоряют процессы чтения и замедляют запись или другие процессы модификации (отсюда и быстрый выбор).
- РЕДАКТИРОВАТЬ: Извините, я не прочитал вопросы полностью. Если таблица пуста, это не может быть проблемой с индексом. или я буду удивлен, если это будет -
Если вы регулярно удаляете все строки из таблицы, «усечь таблицу XXX» обычно намного быстрее, чем массовое удаление. Может быть, попробуйте это и посмотрите, насколько быстрее вы сможете это получить.