Более быстрая альтернатива в Oracle для ВЫБОРА КОЛИЧЕСТВА (*) ИЗ sometable

Существует хорошая реализация Эффективный Java hashcode() и equals() логика в Apache Commons Lang . Контроль HashCodeBuilder и EqualsBuilder.

59
задан Eli Courtwright 3 December 2009 в 15:18
поделиться

6 ответов

Проблема в том, что в приведенном выше коде не используются дженерики .

Будет работать следующее:

Vector<Integer> moves = new Vector<Integer>();

move.add(new Integer(x));

Имя типа внутри <> (в случае Vector параметр типа E для удерживаемого элемента) сообщает компилятору, какой тип объекта следует ожидать.

Если кто-то пытается добавить объект указанного типа, например, в этом случае, пытается добавить String к и Vector , произойдет ошибка времени компиляции, указывающая, что добавляется тип объекта, который не является ожидаемым.

При этом следует стараться не использовать класс Vector . Для большего количества целей В многопользовательской среде мой COUNT (*) может отличаться от вашего COUNT (*) . Было бы непрактично иметь разные счетчики для каждого сеанса, чтобы вам приходилось буквально подсчитывать строки. В любом случае в большинстве случаев у вас будет предложение WHERE или JOIN в вашем запросе, поэтому ваш гипотетический счетчик будет иметь небольшую практическую ценность.

Однако есть способы ускорить процесс: если у вас есть INDEX в столбце NOT NULL Oracle будет считать строки индекса вместо таблицы. В правильной реляционной модели все таблицы имеют первичный ключ, поэтому COUNT (*) будет использовать индекс первичного ключа.

Bitmap index имеет записи для NULL строк, поэтому COUNT (*) будет использовать индекс растрового изображения, если он доступен.

Было бы непрактично иметь разные счетчики для каждого сеанса, чтобы вам приходилось буквально подсчитывать строки. В любом случае в большинстве случаев у вас будет предложение WHERE или JOIN в вашем запросе, поэтому ваш гипотетический счетчик будет иметь небольшую практическую ценность.

Однако есть способы ускорить процесс: если у вас есть INDEX в столбце NOT NULL Oracle будет считать строки индекса вместо таблицы. В правильной реляционной модели все таблицы имеют первичный ключ, поэтому COUNT (*) будет использовать индекс первичного ключа.

Bitmap index имеет записи для NULL строк, поэтому COUNT (*) будет использовать индекс растрового изображения, если он доступен.

Было бы непрактично иметь разные счетчики для каждого сеанса, чтобы вам приходилось буквально подсчитывать строки. В любом случае в большинстве случаев у вас будет предложение WHERE или JOIN в вашем запросе, поэтому ваш гипотетический счетчик будет иметь небольшую практическую ценность.

Однако есть способы ускорить процесс: если у вас есть INDEX в столбце NOT NULL Oracle будет считать строки индекса вместо таблицы. В правильной реляционной модели все таблицы имеют первичный ключ, поэтому COUNT (*) будет использовать индекс первичного ключа.

Bitmap index имеет записи для NULL строк, поэтому COUNT (*) будет использовать индекс растрового изображения, если он доступен.

В любом случае в большинстве случаев у вас будет предложение WHERE или JOIN в вашем запросе, поэтому ваш гипотетический счетчик будет иметь небольшую практическую ценность.

Однако есть способы ускорить процесс: если у вас есть INDEX в столбце NOT NULL Oracle будет считать строки индекса вместо таблицы. В правильной реляционной модели все таблицы имеют первичный ключ, поэтому COUNT (*) будет использовать индекс первичного ключа.

Bitmap index имеет записи для NULL строк, поэтому COUNT (*) будет использовать индекс растрового изображения, если он доступен.

В любом случае в большинстве случаев у вас будет предложение WHERE или JOIN в вашем запросе, поэтому ваш гипотетический счетчик будет иметь небольшую практическую ценность.

Однако есть способы ускорить процесс: если у вас есть INDEX в столбце NOT NULL Oracle будет считать строки индекса вместо таблицы. В правильной реляционной модели все таблицы имеют первичный ключ, поэтому COUNT (*) будет использовать индекс первичного ключа.

Bitmap index имеет записи для NULL строк, поэтому COUNT (*) будет использовать индекс растрового изображения, если он доступен.

29
ответ дан 24 November 2019 в 18:06
поделиться

Если вам нужна только приблизительная оценка, вы можете экстраполировать из образца:

SELECT COUNT (*) * 100 FROM sometable SAMPLE (1);

Для большей скорости (но меньшая точность) вы можете уменьшить размер выборки:

SELECT COUNT (*) * 1000 FROM sometable SAMPLE (0.1);

Для еще большей скорости (но еще худшей точности) вы можете использовать блочную выборку:

SELECT COUNT (*) * 100 FROM sometable SAMPLE BLOCK (1);

58
ответ дан 24 November 2019 в 18:06
поделиться

Если таблица имеет индекс в столбце NOT NULL, то COUNT (*) будет использовать его. В противном случае выполняется полное сканирование таблицы. Обратите внимание, что индекс не обязательно должен быть УНИКАЛЬНЫМ, он просто должен быть НЕ ПУСТОЙ.

Вот таблица ...

SQL> desc big23
 Name                                      Null?    Type
 ----------------------------------------- -------- ---------------------------
 PK_COL                                    NOT NULL NUMBER
 COL_1                                              VARCHAR2(30)
 COL_2                                              VARCHAR2(30)
 COL_3                                              NUMBER
 COL_4                                              DATE
 COL_5                                              NUMBER
 NAME                                               VARCHAR2(10)

SQL>

Сначала мы проведем подсчет без индексов ....

SQL> explain plan for
  2      select count(*) from big23
  3  /

Explained.

SQL> select * from table(dbms_xplan.display)
  2  /
select * from table)dbms_xplan.display)

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
Plan hash value: 983596667

--------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Cost (%CPU)| Time     |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |  1618   (1)| 00:00:20 |
|   1 |  SORT AGGREGATE    |       |     1 |            |          |
|   2 |   TABLE ACCESS FULL| BIG23 |   472K|  1618   (1)| 00:00:20 |
--------------------------------------------------------------------

Note

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
   - dynamic sampling used for this statement

13 rows selected.

SQL>

Нет мы создаем индекс для столбца, который может содержать записи NULL ...

SQL> create index i23 on big23(col_5)
  2  /

Index created.

SQL> delete from plan_table
  2  /

3 rows deleted.

SQL> explain plan for
  2      select count(*) from big23
  3  /

Explained.

SQL> select * from table(dbms_xplan.display)
  2  /

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
Plan hash value: 983596667

--------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Cost (%CPU)| Time     |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     1 |  1618   (1)| 00:00:20 |
|   1 |  SORT AGGREGATE    |       |     1 |            |          |
|   2 |   TABLE ACCESS FULL| BIG23 |   472K|  1618   (1)| 00:00:20 |
--------------------------------------------------------------------

Note

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
   - dynamic sampling used for this statement

13 rows selected.

SQL>

Наконец, давайте создадим индекс для столбца NOT NULL ....

SQL> drop index i23
  2  /

Index dropped.

SQL> create index i23 on big23(pk_col)
  2  /

Index created.

SQL> delete from plan_table
  2  /

3 rows deleted.

SQL> explain plan for
  2      select count(*) from big23
  3  /

Explained.

SQL> select * from table(dbms_xplan.display)
  2  /

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------
Plan hash value: 1352920814

----------------------------------------------------------------------
| Id  | Operation             | Name | Rows  | Cost (%CPU)| Time     |
----------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |     1 |   326   (1)| 00:00:04 |
|   1 |  SORT AGGREGATE       |      |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| I23  |   472K|   326   (1)| 00:00:04 |
----------------------------------------------------------------------

Note

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------
   - dynamic sampling used for this statement

13 rows selected.

SQL>
13
ответ дан 24 November 2019 в 18:06
поделиться

Вариант 1. Иметь индекс для ненулевого столбца, который можно использовать для сканирования. Или создайте функциональный индекс как:

create index idx on t(0);

, затем его можно просканировать, чтобы получить счет.

Вариант 2: Если у вас включен мониторинг, проверьте представление мониторинга USER_TAB_MODIFICATIONS и добавьте / вычтите соответствующие значения в таблицу. статистика.

Вариант 3: Для быстрой оценки больших таблиц вызовите предложение SAMPLE ... например ...

SELECT 1000*COUNT(*) FROM sometable SAMPLE(0.1); 

Вариант 4: Используйте материализованное представление для поддержания счетчика (*). Но мощное лекарство.

ммм ...

7
ответ дан 24 November 2019 в 18:06
поделиться

Вы можете создать материализованное представление с быстрым обновлением для хранения счетчика.

Пример:

create table sometable (
id number(10) not null primary key
, name varchar2(100) not null);

create materialized view log on sometable with rowid including new values;

create materialized view sometable_count
refresh on commit
as
select count(*) count
from   sometable;

insert into sometable values (1,'Raymond');
insert into sometable values (2,'Hans');

commit;

select count from sometable_count; 

Это немного замедлит мутации в таблице sometable, но подсчет станет намного быстрее.

5
ответ дан 24 November 2019 в 18:06
поделиться

Самый быстрый способ подсчета таблицы - это именно то, что вы сделали. Нет никаких уловок, о которых Oracle еще не знает.

Есть кое-что, о чем вы нам не сказали. А именно, почему вы думаете, что это должно быть быстрее?

Например:

  1. Вы хотя бы составили план объяснения, чтобы увидеть, что делает Oracle?
  2. Сколько строк в этой таблице?
  3. Какую версию Oracle вы используете? 8,9,10,11 ... 7?
  4. Вы когда-нибудь запускали статистику базы данных для этой таблицы?
  5. Это часто обновляемая таблица или загружаемый пакет или просто статические данные?
  6. Это единственные медленные COUNT (*) у вас есть?
  7. Сколько времени займет SELECT COUNT (*) FROM Dual?

Признаюсь, я бы не стал Не радуйтесь 41 секунде, но почему вы думаете, что она должна быть быстрее? Если вы скажете нам, что таблица имеет 18 миллиардов строк и работает на ноутбуке, который вы купили на гаражной распродаже в 2001 году, 41 секунда, вероятно, не так уж и далеко от «хорошего, насколько она будет», если вы не приобретете лучшее оборудование. Однако, если вы скажете, что используете Oracle 9 и хорошо провели статистику прошлым летом, вы, вероятно, получите другие предложения.

3
ответ дан 24 November 2019 в 18:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: