2015-10-30 9 views
6

Ich mache einige Datenbank-Benchmarks in Python mit dem CX_Oracle-Modul. Um Benchmark-Ergebnisse zu erzielen, führe ich 150 eindeutige Abfragen aus und beziffere die Ausführung jedes einzelnen. Ich bin mit etwas wie folgt aus:Oracle 11g - Abfrage scheint auch mit NOCACHE Hinweis zu cachen

c = connection.cursor() 
starttime = time.time() 
c.execute('SELECT /*+ NOCACHE */ COUNT (*) AS ROWCOUNT FROM (' + sql + ')') 
endtime = time.time() 
runtime = endtime - starttime 

Jede Abfrage in der durch die variable sql übergeben wird, und sie unterscheiden sich deutlich in der Länge, Laufzeit und die Tabellen sie zugreifen. Davon abgesehen, weisen alle Abfragen folgendes Verhalten:

1. Lauf: sehr langsam (relativ)

2. Lauf: deutlich schneller (dauert überall von 1/2 - 1/5 der Zeit)

3. Lauf: geringfügig schneller als 2. Lauf

Alle nachfolgenden Läufe> = 4: etwa gleich 3. Lauf

Ich brauche den Cache deaktiviert, um genaue Ergebnisse zu erhalten, aber die ersten paar Läufe werfen wirklich meine Daten ab; es ist, als ob NOCACHE überhaupt nicht funktioniert ... was ist hier los?

Edit: Allan beantwortet meine Frage, aber für jeden, der interessiert sein könnte, ich habe ein wenig mehr Forschung und stieß auf diesen beiden Seiten, die auch hilfreich waren:

How to clear all cached items in Oracle

http://www.dba-oracle.com/t_flush_buffer_cache.htm

+2

Sie _want_ das Live-System zu cachen, weil das die Leistung verbessert. Also sollten Sie Ihren Benchmark nicht so arrangieren, dass die ersten beiden Läufe für jede Abfrage verworfen werden (z. B. "Burn-In"). Welche Art von Abfragen haben Sie in 'sql'? Die Art und Weise, wie Sie die Abfrage gerade übergeben, erlaubt nicht die Verwendung von _bind variables_, dh wenn die Abfragen Eingabeparameter enthalten, werden diese in das Abfrageliteral eingebettet, was eine [hard parse] (https: // fragtom) verursacht. oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:2588723819082) jeder Ausführung vorausgehen, was, wie ich annehme, die Verzögerung in # 1 verursacht. –

+0

Ich bin ein wenig verwirrt. Da ich ein Benchmarking mit der Annahme mache, dass die Abfrage in der Produktion hart geparst wird, möchte ich * die langsameren Läufe behalten. Tatsächlich versuche ich, sie alle mit den ersten Läufen in Einklang zu bringen.Diese Situation erfordert Abfragen, die nicht zwischengespeichert werden, da das Testen über mehrere Datenbanken mit unterschiedlichen Konfigurationen stattfindet und die Benutzer auf dem System nur einmal eine Abfrage ausführen, die zwischengespeicherte Zeiten für das Benchmarking ungültig macht. – McGlothlin

+0

Okay, ich wusste nicht, dass Sie Abfragen testen, die nur _once_ in der Produktion ausgeführt werden. Wenn die Abfragen wirklich schwer sind, dann ist das Hard-Parsing hier wahrscheinlich nicht der größte Faktor, stattdessen ist die Ausführung der Abfrage nur langsam. Könnten Sie ein Oracle-Dienstprogramm wie tkprof für das Profiling verwenden? –

Antwort

6

Von der documentation:

Der NOCACHE-Hinweis gibt an, dass die für die Tabelle abgerufenen Blöckesindwird an das zuletzt verwendete Ende der LRU-Liste im Zwischenspeicher platziert, wenn ein vollständiger Tabellenscan durchgeführt wird. Dies ist das normale Verhalten von Blöcken im Puffer-Cache.

Es scheint, dass der nocache Hinweis einfach nicht tut, was Sie erwarten.

Sie können den gemeinsam genutzten Cache löschen, indem Sie ALTER SYSTEM FLUSH SHARED_POOL und den Puffercache ausführen, indem Sie ALTER SYSTEM FLUSH BUFFER_CACHE ausführen. Sie müssen dies zwischen den einzelnen Abfragen durchführen, um zu verhindern, dass der Cache verwendet wird.