2013-06-24 6 views
1

Я пытался получить count(*) со стола, который содержит почти 7 миллионов записей и занимает больше часа для возвращения результата.Oracle count (*) занимает слишком много времени

Также в таблице имеется 153 столбца, из которых индекс создан для столбца 123, поэтому попытался выполнить следующий запрос параллельно, но это не помогло.

select /*+ parallel (5) */ count(123) from <table_name> 

Просьба предложить, если есть альтернативный способ.

Когда я запустил desc на столе в жабе, на вкладке индекса указано значение no. строк. Любая идея, как это значение обновляется там?

+1

я предполагаю, что на 'подсчета (123)' вы имеете в виду 'count (column_123)', правильно? – Bohemian

+0

'select/* + parallel (5) */count (123) from' Я думаю, вы случайно запросили. –

+1

Вы видели это: http://stackoverflow.com/questions/1840538/faster-alternative-in-oracle-to-select-count-from-sometable? – LMeyer

ответ

2

Подсчет количества строк большой таблицы занимает много времени. Это естественно. В некоторых СУБД хранится количество записей, однако эти типы СУБД ограничивают параллелизм. Он должен заблокировать всю таблицу перед операцией DML в таблице. (Вся блокировка таблицы необходимо обновить отсчет должным образом.)

Значение в ALL_TABLES.NUM_ROWS (или USER_TABLES.NUM_ROWS) только статистическая информация, полученная с помощью analyze table ... или dbms_stats.gather_table_stats процедуры. Это неточность, а не информация в режиме реального времени.

Если вам не нужно точное количество строк, вы можете использовать статистическую информацию. Однако вы не должны зависеть от этого. Он используется оптимизатором Oracle, но не должен применяться в прикладной программе.

Я не уверен, почему вам приходится подсчитывать количество строк таблицы. Если вам это нужно в пакетной программе, которая выполняется нечасто, вы можете разбить таблицу, чтобы увеличить параллельность. Если вам нужен счет в онлайн-программе, вы должны найти способ не использовать счет.

+1

+1 Но в целом параллелизм и разбиение не зависят друг от друга. Это было менее верно в более старых версиях, и все еще есть места, где параллелизм и разбиение должны работать вместе, например, с помощью соединений по разделам. Но для простого подсчета всех строк разделение экстентов между 5 различными процессами, вероятно, не принесло бы пользы от разбиения. –

+1

Вот еще информация о [Granules of Parallelism] (http://docs.oracle.com/cd/E11882_01/server.112/e25523/parallel002.htm#BEIIGIFH), если вам интересно. –

+0

@jonearles Да, вы правы. Благодарим вас за вашу доброту и полезную информацию. – ntalbs

0
select /*+ parallel (5) */ 

Похоже на нечетное число для степени параллелизма. Ну, очевидное 5 - это нечетное число, и это странно. DoP должны быть мощностью, кратным двум (подробнее см. Ниже).

Во всяком случае, есть ли у вас причина использовать параллельный запрос? У вас есть как минимум пять запасных процессоров? Если нет, есть хороший шанс, что накладные расходы на управление ведомыми устройствами PQ по меньшей мере способствуют низкой производительности.


Почему DOP = n * 2? Существует установленная эвристика, основанная на теории Queuing Theory, которая одновременно запускает более двух пакетных заданий, что приводит к снижению производительности. Find out more. (думаю, теория массового обслуживания фактически рекомендует цифру 1,8, но поскольку задания базы данных часто связаны с I/O или диском, мы обычно можем уйти с 2.)

Я изначально сказал «сила 2», но это в основном потому что многоядерные серверы имеют несколько процессоров, мощность которых равна 2, но несколько из них более точны, потому что в некоторых коробках есть 12 процессоров или какое-то другое число.

Теперь, если у нас есть 64-ядерный ящик, DOP 5 или 37 - это нормально, потому что у нас достаточно процессоров для одновременного запуска многих потоков. Но если у нас есть небольшой квадрат quadcore, только 2, 4 или 8 имеет смысл, потому что это единственные значения, которые обеспечат равномерное распределение работы для всех четырех процессоров. Выполнение пяти потоков на четырехъядерном ящике означает, что один процессор будет выполнять гораздо больше работы, чем другие три; есть вероятность, что потребуется больше времени для завершения, оставив остальных трех рабов.Таким образом, DOP=5 может фактически привести к большему истекшему времени, чем DOP=4.

DOP=n*2 - это только эмпирическое правило, а не камень. Однако он основан на здравых рассуждениях, и мы должны знать, почему мы делаем что-то другое. Очевидно, мы должны были провести некоторые эксперименты, чтобы подтвердить, что мы выбрали правильную ДОП (независимо от того, какое значение мы установим).

+0

Почему DOP должна быть силой двух? Вы думаете о количестве хэш-разделов вместо этого? –

+0

@jonearles - нет, я определенно думаю о параллельном запросе. Эмпирическое правило для DOP - 2 * ЦП (при условии, что в системе нет других процессов, конкурирующих за ресурс). Хотя причина такая же, как и для хэш-разделов - даже распределение, в данном случае рабочей нагрузки. – APC

+0

Правило 2 правила полезно для хэш-разбиения из-за того, как работает ORA_HASH. Но я не могу найти источник, который подразумевает, что ORA_HASH или аналогичная функция играет роль в распределении блоков на параллельные серверы. Я предполагаю, что, однако, список блоков и экстентов сохраняется, для этого запроса просто взять этот список и разбить его на N групп. Разделение на 5 должно работать так же, как 4 или 8. И я видел множество примеров Oracle и некоторых автодокументов, которые не являются полномочиями 2. Число почти всегда кратно 2, но мне интересно, действительно ли это действительно вопросы. –

2

Несколько вопросов говоря:

  1. Для «SELECT COUNT (*) из таблицы», чтобы использовать индекс, индексированный столбец должен быть не обнуляемым, или индекс должен быть тип растрового изображения.
  2. Если в столбце известно, что в столбце нет нулей, но на нем нет нулевого ограничения, тогда используйте «select count (*) из таблицы, где column_name не равно null».
  3. Разумеется, для сканирования индекса нужно быть более эффективным, чем таблица, но с таким количеством столбцов таблицы, вы, вероятно, прекрасно там.
  4. Если вы действительно хотите сканирование параллельного индекса, используйте подсказку parallel_index, а не параллель. Но с 7 миллионами строк вам может не понадобиться параллелизм.
  5. Вам нужно проверить план выполнения, чтобы увидеть, используется ли индекс и/или параллельный запрос.
  6. Если вы можете использовать оценочное количество строк, то рассмотрим, используя пункт выборки: например, «выбрать 1000 * COUNT (*) из таблицы образца (0.1)»