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.