Às vezes você quer usar as coisas com opções default.. e às vezes o default não é bom o suficiente.
A gente sabe que o db_file_multiblock_read_count é bumpado por default no startup, normalmente você pega 128 blocks por read. Por quê?
Da documentação Oracle, esse valor é alto, mas o CBO não vai favorecer full table scans.
“Even though the default value may be a large value, the optimizer will not favor large plans if you do not set this parameter. It would do so only if you explicitly set this parameter to a large value.”
Beleza. Mas por quê? De um 10053 trace dentro de uma sessão, você pode ver que o CBO vai computar o db_file_multiblock_read_count sempre como “8”.. mesmo se você ver 128 no spfile.
O CBO sempre vai usar 8 se você não setar db_file_multiblock_read_count explicitamente. Como saber se você setou db_file_multiblock_read_count como 128? Usa isso:
SELECT nvl(value,’*NULL*’) AS value FROM v$spparameter WHERE name = ‘db_file_multiblock_read_count’;
Se isso retornar *NULL*, você não setou db_file_multiblock_read_count, Oracle está te mostrando 128, mas o CBO usa 8. Triste, né?
Vocês todos leram a documentação e sabem os efeitos de bumpar db_file_multiblock_read_count alto. Full table scans vão acontecer com mais frequência e, como resultado, num sistema OLTP, normalmente você recebe uma ligação do seu chefe (hehe)
Mas tem um jeito de setar corretamente o db_file_multiblock_read_count.. testando.. por exemplo, dá uma olhada no bloco abaixo. É bobo, eu sei, mas pode te dar um valor mágico pra esse parâmetro.
set serveroutput on DECLARE l_count PLS_INTEGER; l_time PLS_INTEGER; l_starting_time PLS_INTEGER; l_ending_time PLS_INTEGER; BEGIN dbms_output.put_line(‘dbfmbrc seconds’); FOR l_dbfmbrc IN 1..64 LOOP EXECUTE IMMEDIATE ‘ALTER SESSION SET db_file_multiblock_read_count=’||l_dbfmbrc; EXECUTE IMMEDIATE ‘ALTER system flush buffer_cache’; EXECUTE IMMEDIATE ‘ALTER session disable parallel dml’; l_starting_time := dbms_utility.get_time(); SELECT /*+ full(t) */ count(*) INTO l_count FROM big_table t; l_ending_time := dbms_utility.get_time(); l_time := round((l_ending_time-l_starting_time)/100); dbms_output.put_line(l_dbfmbrc||’ ‘||l_time); END LOOP; END; /
(Obrigado Chris Antognini, você é incrível)
Com esse bloco (cuidado, ele vai levar 60-90 minutos dependendo do tamanho da big table, como conselho, usa uma tabela de 5GB), você vai ter valores, plota um gráfico e vê o comportamento. Não escolhe um valor alto pra OLTP.
Falamos!