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

View File

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