Проблема такая.
Есть база oracle. Есть прилада. Прилада выводит большое количество данных в постраничном режиме. При этом пользователь очень-очень хочет видеть не просто "вперед-назад" — а сколько в точности есть записей и сколько еще страниц осталось.
В результате используется count на данные по тому фильтру который наложил пользователь и показ одной текущей страницы для пользователя.
Результат. Разница между выборкой одной страницы и выполнением count — на несколько порядков.
(по относительно крупной таблице по достаточно "общему" фильтру получается вывод одной страницы занимает где-то в пределах сотой доли секунды, count — 5-10 секунд)
Быстродействие в результате ни к черту. Но заказчик твердо хочет видеть число записей, удовлетворяющих фильтру.
Можно ли как-то ускорить подсчет количества данных, удовлетворяющих фильтру? Индексы на поля, по которым фильтр проводится — наложены.
Здравствуйте, fmiracle, Вы писали:
F>Проблема такая. F>Есть база oracle. Есть прилада. Прилада выводит большое количество данных в постраничном режиме. При этом пользователь очень-очень хочет видеть не просто "вперед-назад" — а сколько в точности есть записей и сколько еще страниц осталось.
F>В результате используется count на данные по тому фильтру который наложил пользователь и показ одной текущей страницы для пользователя.
F>Результат. Разница между выборкой одной страницы и выполнением count — на несколько порядков. F>(по относительно крупной таблице по достаточно "общему" фильтру получается вывод одной страницы занимает где-то в пределах сотой доли секунды, count — 5-10 секунд)
F>Быстродействие в результате ни к черту. Но заказчик твердо хочет видеть число записей, удовлетворяющих фильтру.
F>Можно ли как-то ускорить подсчет количества данных, удовлетворяющих фильтру? Индексы на поля, по которым фильтр проводится — наложены.
Здравствуйте, fmiracle, Вы писали:
F>пользователь очень-очень хочет видеть не просто "вперед-назад" — а сколько в точности есть записей и сколько еще страниц осталось.
Желание обоснованное (бизнес-процессом) или аргументы типа "почему Access может а вы нет"?
F>(по относительно крупной таблице по достаточно "общему" фильтру получается вывод одной страницы занимает где-то в пределах сотой доли секунды, count — 5-10 секунд) F>Быстродействие в результате ни к черту. Но заказчик твердо хочет видеть число записей, удовлетворяющих фильтру.
Если 5-10 секунд для заказчика приемлемы, то делайте count.
F>Можно ли как-то ускорить подсчет количества данных, удовлетворяющих фильтру? Индексы на поля, по которым фильтр проводится — наложены.
Кардинально нет. Можно использовать аналитику (count over) и обойтись одним запросом. Заодно и результаты будут согласованными, в отличие от отдельного count.
Здравствуйте, sunsquirel, Вы писали:
S>Скажите, а Вы делаете count(*) или как?
count(*)
Re: Можно ли ускорить count в Oracle?
От:
Аноним
Дата:
11.04.08 04:40
Оценка:
Нужно посмотреть explain plan, используются ли индексы вообще? Какой медод доступа к базе (ADO, OO4O) ?
Разница от того, что Ораклу для count(*) надо всё-таки данные перебрать все чтобы получить точное количество результирующих записей, а для пары-тройки несортированых записей скорость на порядок быстрее.
По моему опыту, OO4O работает со страницами гораздо лучше. Смотреть тут http://www.orafaq.com/faqoo4o.htm
В зависимости от количества данных и предназначения запроса может иметь смысл огранизовать специальную таблицу в которой будут собираться все интересующие записи, готовые к выводу на экран. И уже на эту таблицу накладывать фильтры, считать количество записей и т.д.
F>Быстродействие в результате ни к черту. Но заказчик твердо хочет видеть число записей, удовлетворяющих фильтру.
а индекс на таблице есть?
может hiwatermark высоко задран и таблицу нужно реорганизовать?
сколько всего строк в таблице?
Здравствуйте, JazzzMaster, Вы писали:
N>>может hiwatermark высоко задран и таблицу нужно реорганизовать? JM>кстати, интересно, а можно ли его как-нибудь "понизить" не используя truncate ?
Здравствуйте, Аноним, Вы писали: А>Разница от того, что Ораклу для count(*) надо всё-таки данные перебрать все чтобы получить точное количество результирующих записей, а для пары-тройки несортированых записей скорость на порядок быстрее.
Нет никакой разницы, count(*) или count(1). Это все urban legend миллион раз опровергнутые. Execution plan пбсолютно одинаков, к тому же
в каждой1 второй книжке по оптимизации постоянно пишут, что скорость выборки не зависит от количества полей перечисляемых в запросе.
Здравствуйте, krot_av, Вы писали:
_>Нет никакой разницы, count(*) или count(1). Это все urban legend миллион раз опровергнутые.
К чему здесь этот флуд? Никто не предлагал count(1).
_>скорость выборки не зависит от количества полей перечисляемых в запросе.
А это неверно.
Здравствуйте, wildwind, Вы писали:
_>>скорость выборки не зависит от количества полей перечисляемых в запросе. W>А это неверно.
Execution plan будет одинаковым, вся разница только в передаваемых объемах данных по сети.
Здравствуйте, krot_av, Вы писали:
_>>>скорость выборки не зависит от количества полей перечисляемых в запросе. W>>А это неверно. _>Execution plan будет одинаковым, вся разница только в передаваемых объемах данных по сети.
И это неверно. Подумай об индексах.
Здравствуйте, wildwind, Вы писали:
W>И это неверно. Подумай об индексах.
Использование индексов зависит не от полей перечисленных в select, а от условий WHERE.
Так что никакого влияние на индексы select * или select some field не окажет, да и не должен оказывать.
Здравствуйте, krot_av, Вы писали:
W>>И это неверно. Подумай об индексах. _>Использование индексов зависит не от полей перечисленных в select, а от условий WHERE. _>Так что никакого влияние на индексы select * или select some field не окажет, да и не должен оказывать.
Не упорствуй в своем заблуждении. Сравни планы для "select pk from table" и "select * from table" для обычной (heap) таблицы.
W>Не упорствуй в своем заблуждении. Сравни планы для "select pk from table" и "select * from table" для обычной (heap) таблицы.
Я их сравнивал в оракл и DB2.
Если говоритиь о заблуждениях, то будет тебе известно, что для приведенных тобой запросов будет использован full scan в любом случае.
Здравствуйте, krot_av, Вы писали:
_>Здравствуйте, wildwind, Вы писали:
W>>Не упорствуй в своем заблуждении. Сравни планы для "select pk from table" и "select * from table" для обычной (heap) таблицы.
_>Я их сравнивал в оракл и DB2.
Продемонстрируй! Или просто скажи что проверять было лень.
Вот мой пример:
SQL> create table test_tab as select rownum id, rpad('*', 2000, '*') text from all_objects;
Таблица создана.
SQL> alter table test_tab add constraint test_tab_pk primary key (id);
Таблица изменена.
SQL> exec dbms_stats.gather_table_stats(user, 'test_tab', cascade => true)
Процедура PL/SQL успешно завершена.
SQL> set autotrace traceonly
SQL> set timing on
SQL> select * from test_tab;
83692 строк выбрано.
Затрач.время: 00:00:09.34
План выполнения
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=8264 Card=83692 Bytes=167802460)
1 0 TABLE ACCESS (FULL) OF 'TEST_TAB' (Cost=8264 Card=83692 Bytes=167802460)
Статистика
----------------------------------------------------------
0 recursive calls
0 db block gets
83706 consistent gets
83692 physical reads
0 redo size
1274661 bytes sent via SQL*Net to client
61730 bytes received via SQL*Net from client
5581 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
83692 rows processed
SQL> select id from test_tab;
83692 строк выбрано.
Затрач.время: 00:00:05.93
План выполнения
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=40 Card=83692 Bytes=418460)
1 0 INDEX (FAST FULL SCAN) OF 'TEST_TAB_PK' (UNIQUE) (Cost=40 Card=83692 Bytes=418460)
Статистика
----------------------------------------------------------
0 recursive calls
0 db block gets
5915 consistent gets
357 physical reads
0 redo size
949057 bytes sent via SQL*Net to client
61730 bytes received via SQL*Net from client
5581 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
83692 rows processed
SQL> disc
Отсоединено от Oracle9i Enterprise Edition Release 9.2.0.7.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.7.0 - Production
_>Если говоритиь о заблуждениях, то будет тебе известно, что для приведенных тобой запросов будет использован full scan в любом случае.
full scan он разный бывает.
Здравствуйте, Neco, Вы писали:
JM>>кстати, интересно, а можно ли его как-нибудь "понизить" не используя truncate ? N>alter table move?
а для индексов — alter index rebuild tablespace
Здравствуйте, wildwind, Вы писали:
_>>Если говоритиь о заблуждениях, то будет тебе известно, что для приведенных тобой запросов будет использован full scan в любом случае. W>full scan он разный бывает.
Странно, но мне то же самое поведение смоделировать не удалось. В обоих случаях случаях был использован full scan
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'T1'
Oracle правда восьмой
SQL> select banner from v$version;
BANNER
----------------------------------------------------------------
Oracle8i Enterprise Edition Release 8.1.7.4.0 — Production
PL/SQL Release 8.1.7.4.0 — Production
CORE 8.1.7.0.0 Production
TNS for Solaris: Version 8.1.7.4.0 — Production
NLSRTL Version 3.4.1.0.0 — Production
_>в каждой1 второй книжке по оптимизации постоянно пишут, что скорость выборки не зависит от количества полей перечисляемых в запросе.
если идет сканирование по индексу и все поля в кляузе select входят в этот индекс, то, разумеется, такой запрос будет отрабатывать эффективнее, т.к. позволяет брать данные напрямую из индекса, избегая, например, table access by rowid для Oracle(либо аналогов для других СУБД)