Godiva, pojďmě si představit další funkci z balíčku funkcí, které tu jsou nově v 12.1c – APPROX_COUNT_DISTINCT. Jak název napovídá funkce vrátí počet distinctních hodnot a slovo APPROX znamená, že je to “asi tak nějak” Výměnou za nějakou tu nepřesnost dostaneme mnohonásobné zrychlení. Takže hurá na nějaký test a další informace dále :
CREATE TABLE TEST_APROX( ID NUMBER(30) PRIMARY KEY, TEST_RANDOM NUMBER, TEST_1_100 NUMBER, TEST_1_2_3 NUMBER, TEST_1_25000 NUMBER, TEST_10_1 NUMBER );
A ještě je třebas jí naplnit:
begin for i in 0..100 loop INSERT INTO TEST_APROX SELECT ROWNUM+(i*30000) AS ID, dbms_random.value AS TEST_RANDOM, MOD(rownum,100) AS TEST_1_100, CASE WHEN ROWNUM=15555 THEN 1 WHEN ROWNUM=15556 THEN 2 ELSE 3 END AS TEST_1_2_3, CASE WHEN ROWNUM<25000 THEN 1 ELSE ROWNUM END AS TEST_1_25000, CASE WHEN MOD(ROWNUM,10)<>2 THEN MOD(ROWNUM,10) ELSE 1 END AS TEST_10_1 FROM dual CONNECT BY LEVEL <=30000; end loop; end;
Tak nějak nějaký vzorek dat, některá lehce zkosená některá náhodná. Doporučuji případně ještě napočítat statistiky během CTASu se sice nově napočítávají, ale takhle v LOOPu to nezafunguje, bohužel. Mě to vychází nějak takto:
Sloupec | Popis dat | DISTINCT | APR CNT DIS | APR CNT DIS result | Chyba |
ID | Čísla od 1 do 3030000 | 2,8 (jedeme po indexu) | 1s | 2975859 | 1,78% |
TEST_RANDOM | Náhodná čísla | cca 19s | 1s | 2986718 | 1,42% |
TEST_1_100 | Čísla od 0 do 99, každé 30300x | 2s | pod 1s | 100 | 0% |
TEST_1_2_3 | čísla 1,2 101x číslo 3 3029798x | pod 1s | pod 1s | 3 | 0% |
TEST_1_25000 | 1x 2524899,101x 25000-30000 | 1s-2s | pod 1s | 5018 | 3,2% |
TEST_10_1 | 30300x 0,3-9, 606000x 1 | 1s-2s | pod 1s | 9 | 0% |
Takže nějaký závěr: narozdíl od DISTINCT se závislost na datech neprojeví zpomalením, ale na nepřesnosti. Což je hodně sympatické, bohužel jsem podcenil svůj komp a zrychení je vidět de-facto jen ve dvou případech, ale i tak je vidět že o proti normálnímu COUNTU hraje APPROX_COUNT_DISTINCT naprosto jinou ligu A to i proti indexu je daleko rychlejšejší. V exekučním plánu to vypadá nějak takto:

Aprox exekuční plán
Nicméně ačkoliv to ukazuje sort mě se na tomhle příkladu nic reálně nesortovalo, jestli to takhle zafunguje budeme muset zjistit Enjoy APPROX_COUNT_DISTINCT !