4

Kann jemand bitte ein Beispiel geben, um das zu verstehen?Was ist ein mysql gepufferter Cursor w.r.t Python mysql Konnektor

Nach Ausführen einer Abfrage ruft ein MySQLCursorBuffered-Cursor die gesamte Ergebnismenge vom Server ab und puffert die Zeilen. Bei Abfragen, die mit einem gepufferten Cursor ausgeführt werden, geben Zeilenabrufmethoden wie fetchone() Zeilen aus dem Satz gepufferter Zeilen zurück. Bei nicht gepufferten Cursorn werden Zeilen erst vom Server abgerufen, wenn eine Zeilenabrufmethode aufgerufen wird. In diesem Fall müssen Sie sicherstellen, dass Sie alle Zeilen der Ergebnismenge abrufen, bevor Sie andere Anweisungen für dieselbe Verbindung ausführen, oder eine InternalError-Ausnahme (Ungelesenes Ergebnis gefunden) wird ausgelöst.

Dank

Antwort

1

Ich denke an zwei Möglichkeiten, können diese beiden Arten von Cursor s unterschiedlich sind. Wenn Sie eine Abfrage mit einem gepufferten Cursor ausführen, können Sie die Anzahl der zurückgegebenen Zeilen ermitteln, indem Sie MySQLCursorBuffered.rowcount überprüfen. Das Attribut rowcount eines ungepufferten Cursors gibt jedoch -1 direkt nach dem Aufruf der execute-Methode zurück. Dies bedeutet im Wesentlichen, dass die gesamte Ergebnismenge noch nicht vom Server abgeholt wurde. Darüber hinaus erhöht sich das rowcount Attribut eines ungepufferten Cursors, wie Sie Zeilen davon abrufen, während das rowcount Attribut eines gepufferten Cursors gleich bleibt, wie Sie Zeilen davon abrufen.

Das folgende Snippet-Code versucht, die Punkte zu illustrieren gemacht oben:

import mysql.connector 


conn = mysql.connector.connect(database='db', 
           user='username', 
           password='pass', 
           host='localhost', 
           port=3306) 

buffered_cursor = conn.cursor(buffered=True) 
unbuffered_cursor = conn.cursor(buffered=False) 

create_query = """ 
drop table if exists people; 
create table if not exists people (
    personid int(10) unsigned auto_increment, 
    firstname varchar(255), 
    lastname varchar(255), 
    primary key (personid) 
); 
insert into people (firstname, lastname) 
values ('Jon', 'Bon Jovi'), 
('David', 'Bryan'), 
('Tico', 'Torres'), 
('Phil', 'Xenidis'), 
('Hugh', 'McDonald') 
""" 

# Create and populate a table 
results = buffered_cursor.execute(create_query, multi=True) 
conn.commit() 

buffered_cursor.execute("select * from people") 
print("Row count from a buffer cursor:", buffered_cursor.rowcount) 
unbuffered_cursor.execute("select * from people") 
print("Row count from an unbuffered cursor:", unbuffered_cursor.rowcount) 

print() 
print("Fetching rows from a buffered cursor: ") 

while True: 
    try: 
     row = next(buffered_cursor) 
     print("Row:", row) 
     print("Row count:", buffered_cursor.rowcount) 
    except StopIteration: 
     break 

print() 
print("Fetching rows from an unbuffered cursor: ") 

while True: 
    try: 
     row = next(unbuffered_cursor) 
     print("Row:", row) 
     print("Row count:", unbuffered_cursor.rowcount) 
    except StopIteration: 
     break 

Die obige Snippet sollte in etwa wie folgt zurück:

Row count from a buffered reader: 5 
Row count from an unbuffered reader: -1 

Fetching rows from a buffered cursor: 
Row: (1, 'Jon', 'Bon Jovi') 
Row count: 5 
Row: (2, 'David', 'Bryan') 
Row count: 5 
Row: (3, 'Tico', 'Torres') 
Row count: 5 
Row: (4, 'Phil', 'Xenidis') 
Row count: 5 
Row: (5, 'Hugh', 'McDonald') 
Row: 5 

Fetching rows from an unbuffered cursor: 
Row: (1, 'Jon', 'Bon Jovi') 
Row count: 1 
Row: (2, 'David', 'Bryan') 
Row count: 2 
Row: (3, 'Tico', 'Torres') 
Row count: 3 
Row: (4, 'Phil', 'Xenidis') 
Row count: 4 
Row: (5, 'Hugh', 'McDonald') 
Row count: 5 

Wie Sie das rowcount Attribut für die sehen können ungepufferter Cursor beginnt bei -1 und erhöht sich, wenn wir das Ergebnis, das es generiert, durchlaufen. Dies ist beim gepufferten Cursor nicht der Fall.

Die zweite Möglichkeit, den Unterschied zu erkennen, besteht darin, darauf zu achten, welche der beiden (unter der gleichen Verbindung) execute zuerst. Wenn Sie mit der Ausführung eines ungepufferten Cursors beginnen, dessen Zeilen nicht vollständig abgerufen wurden, und dann versuchen, eine Abfrage mit dem gepufferten Cursor auszuführen, wird eine Exception InternalError ausgelöst, und Sie werden aufgefordert, den vom ungepufferten Cursor zurückgegebenen Wert zu konsumieren . Im Folgenden finden Sie eine Abbildung:

import mysql.connector 


conn = mysql.connector.connect(database='db', 
           user='username', 
           password='pass', 
           host='localhost', 
           port=3306) 

buffered_cursor = conn.cursor(buffered=True) 
unbuffered_cursor = conn.cursor(buffered=False) 

create_query = """ 
drop table if exists people; 
create table if not exists people (
    personid int(10) unsigned auto_increment, 
    firstname varchar(255), 
    lastname varchar(255), 
    primary key (personid) 
); 
insert into people (firstname, lastname) 
values ('Jon', 'Bon Jovi'), 
('David', 'Bryan'), 
('Tico', 'Torres'), 
('Phil', 'Xenidis'), 
('Hugh', 'McDonald') 
""" 

# Create and populate a table 
results = buffered_cursor.execute(create_query, multi=True) 
conn.commit() 

unbuffered_cursor.execute("select * from people") 
unbuffered_cursor.fetchone() 
buffered_cursor.execute("select * from people") 

Das Snippet oben eine InternalError Ausnahme mit einer Meldung darauf hingewiesen erhöhen wird, dass es einige ungelesene Ergebnis. Im Grunde heißt das, dass das vom ungepufferten Cursor zurückgegebene Ergebnis vollständig verbraucht sein muss, bevor Sie eine weitere Abfrage mit einem Cursor unter derselben Verbindung ausführen können. Wenn Sie unbuffered_cursor.fetchone() mit unbuffered_cursor.fetchall() ändern, wird der Fehler verschwinden.

Es gibt andere weniger offensichtliche Unterschiede, z. B. Speicherverbrauch. Der gepufferte Cursor verbraucht wahrscheinlich mehr Speicher, da er die gesamte Ergebnismenge vom Server holt und die Zeilen zwischenspeichert.

Ich hoffe, das erweist sich als nützlich.