Performance optiomizations:

- Result sets
Convert named_tuple and dictinuary result sets directly from netbuffer,
instead to fetch them in tuples and convert it afterwards

- fetch rows()
Use MrdbCursor_fetchrows() c function for fetchmany/fetchall.
This commit is contained in:
Georg Richter
2022-10-09 11:15:46 +02:00
parent afbd4e35f8
commit e7441f1e59
2 changed files with 23 additions and 36 deletions

View File

@ -18,7 +18,6 @@
#
import mariadb
import collections
import datetime
from numbers import Number
from mariadb.constants import CURSOR, STATUS, CAPABILITY, INDICATOR
@ -28,6 +27,8 @@ PARAMSTYLE_QMARK = 1
PARAMSTYLE_FORMAT = 2
PARAMSTYLE_PYFORMAT = 3
ROWS_ALL = -1
RESULT_TUPLE = 0
RESULT_NAMEDTUPLE = 1
RESULT_DICTIONARY = 2
@ -410,17 +411,7 @@ class Cursor(mariadb._mariadb.cursor):
self.check_closed()
row = self._fetch_row()
if not row:
return row
if self._resulttype == RESULT_DICTIONARY:
ret = dict(zip(list(d[0] for d in self.description), row))
elif self._resulttype == RESULT_NAMEDTUPLE:
ret = collections.namedtuple('Row1', list(d[0]
for d in self.description))
ret = ret._make(row)
else:
ret = row
return ret
return row
def fetchmany(self, size: int = 0):
"""
@ -440,13 +431,9 @@ class Cursor(mariadb._mariadb.cursor):
"""
self.check_closed()
rows = []
if size == 0:
size = self.arraysize
for count in range(0, size):
row = self.fetchone()
if row:
rows.append(row)
rows = super().fetchrows(size)
return rows
def fetchall(self):
@ -458,7 +445,7 @@ class Cursor(mariadb._mariadb.cursor):
produce a result set or execute() wasn't called before.
"""
self.check_closed()
rows = super().fetchall()
rows = super().fetchrows(ROWS_ALL)
if self._connection._converter:
for idx, row in enumerate(rows):
@ -474,19 +461,7 @@ class Cursor(mariadb._mariadb.cursor):
tmp_l[i] = v
rows[idx] = tuple(tmp_l)
if self._resulttype == RESULT_TUPLE:
return rows
ret = []
for row in rows:
if self._resulttype == RESULT_DICTIONARY:
new_row = dict(zip(list(d[0] for d in self.description), row))
elif self._resulttype == RESULT_NAMEDTUPLE:
new_row = collections.namedtuple('Row1', list(d[0]
for d in self.description))
new_row = new_row._make(row)
ret.append(new_row)
return ret
return rows
def __iter__(self):
return iter(self.fetchone, None)

View File

@ -40,7 +40,7 @@ static PyObject *
MrdbCursor_execute_text(MrdbCursor *self, PyObject *args);
static PyObject *
MrdbCursor_fetchall(MrdbCursor *self);
MrdbCursor_fetchrows(MrdbCursor *self, PyObject *args);
static PyObject *
MrdbCursor_parse(MrdbCursor *self, PyObject *args);
@ -128,8 +128,8 @@ static PyMethodDef MrdbCursor_Methods[] =
{"fetchone", (PyCFunction)MrdbCursor_fetchone,
METH_NOARGS,
cursor_fetchone__doc__,},
{"fetchall", (PyCFunction)MrdbCursor_fetchall,
METH_NOARGS,
{"fetchrows", (PyCFunction)MrdbCursor_fetchrows,
METH_VARARGS,
NULL},
{"_nextset", (PyCFunction)MrdbCursor_nextset,
METH_NOARGS,
@ -193,6 +193,11 @@ static struct PyMemberDef MrdbCursor_Members[] =
offsetof(MrdbCursor, parseinfo.command),
0,
MISSING_DOC},
{"_resulttype",
T_UINT,
offsetof(MrdbCursor, result_format),
0,
MISSING_DOC},
{"_text",
T_BOOL,
offsetof(MrdbCursor, parseinfo.is_text),
@ -1212,10 +1217,17 @@ error:
}
static PyObject *
MrdbCursor_fetchall(MrdbCursor *self)
MrdbCursor_fetchrows(MrdbCursor *self, PyObject *args)
{
PyObject *List;
unsigned int field_count= self->field_count;
uint64_t row_count;
if (!PyArg_ParseTuple(args, "K", &row_count))
{
return NULL;
}
MARIADB_CHECK_STMT(self);
@ -1231,7 +1243,7 @@ MrdbCursor_fetchall(MrdbCursor *self)
return NULL;
}
while (!MrdbCursor_fetchinternal(self))
for (uint64_t i=0; i < row_count && !MrdbCursor_fetchinternal(self); i++)
{
uint32_t j;
PyObject *Row;