Working on Windows 10 (development) and Windows Server 2016 (production)
Running Apache 2.4.26 (64bit), MySQL 8.0.11 (64 bit)
I am working on porting an old student information system for public schools from an ancient MS Access+ClassicASP system to MySQL. Last summer I began the conversion using Apache+PHP+MySQL5.7 but ran out of summer (I am also a teacher). All winter I thought about resuming the work but using Python3+MySQL8 instead, and converting my PHP work from last summer as the jumping off point. As I began running the first several converted scripts, I noticed that they were running slower in Python than in PHP, even using the same MySQL instance and the same Apache server.
I have tried several variants of Python MySQL drivers:
- MySQLdb (the syntax of which matches what I teach my students to use on an Ubuntu server)
- mysql.connector (from Oracle)
- PyMySQL
The script I am using to compare PHP and Python simply receives POST data via JQuery, constructs the appropriate SQL command, and performs an update or delete query. The script is basically taking data from a form and when the form content changes (detected with javascript), it changes the caller's text field's background color to red (indicating the change is underway), fires off the ajax request, and when JQuery gets a successful response, the script changes the text field color to green (indicating a successful change). The reason I mention this is that when I use PHP, the red-to-green transition is very fast (you hardly notice). But when I use a Python script as the form's action instead of the PHP script, the delay is very noticable.
Using Chrome's developer's tools, the network option shows the time waiting for the first bytes back (TTFB) and this is the key difference I am using for performance analysis. I ran each script (the one that does the lowest level operations) 4 times. No other users were using the database (it is on my laptop). No other programs were busy in the background. I broke down the times for these 4 trials by starting with all the database parts commented out. Then I un-commented out sections one at a time and ran the script from the calling web page multiple times to get average times. The 4 trials were separated as follows:
- All it did was get the POST data and build the SQL string - no actual database interaction at all.
- It did the above and connected to the database.
- It did the above and submitted the query but did not commit it.
- It did the above AND committed the transaction.
Below is how each of these trials performed for the different methods of connecting to MySQL.
I just kept changing a simple varchar(4) field from "1" to "2" and back again.
===================================================================================================================
With Python and PyMySQL
- TTFB = 130 ms
- TTFB = 170 ms (actually varied 150 - 200 ms : I did this multiple times to be sure it wasn't recompiling after my change)
- TTFB = 180 ms
- TTFB = 200 ms (as high as 250 ms)
Code used:
import pymysql.cursors
connection = pymysql.connect(host='myhost',user='me',password='something',db='mydb',charset='utf8mbr4',cursorclass=pymysql.cursors.DictCursor)
with connection.cursor() as cursor:
cursor.execute(SQL)
connection.commit()
===================================================================================================================
With Python and MySQLdb
- TTFB = 130 ms
- TTFB = 190 ms
- TTFB = 193 ms
- TTFB = 230 ms (as high as 270 ms)
Code used:
import MySQLdb
import MySQLdb.cursors as cursors
dbconn = MySQLdb.connect(host='myhost',user='me',password='something',database='mydb',cursorclass=cursors.DictCursor)
cursor = dbconn.cursor()
cursor.execute(SQL)
dbconn.commit()
===================================================================================================================
With Python and mysql.connector
- TTFB = 130 ms
- TTFB = 440ms! A huge jump.
- TTFB = 450 ms
- TTFB = 500 ms (as high as 580 ms)
Code used:
import mysql.connector
dbconn = mysql.connector.connect(host='myhost',user='me',password='something',database='mydb')
cursor = dbconn.cursor(dictionary=True)
cursor.execute(SQL)
dbconn.commit()
===================================================================================================================
With PHP and mysqli, the TTFB = 270ms (about 170ms for the update and 100ms for the commit)
- TTFB = 3 ms
- TTFB = 6 ms
- TTFB = N/A (it does not need a separate commit())
- TTFB = 50 ms (as low as 10 ms and as high as 70 ms)
Code used:
$dbc = @mysqli_connect('myhost', 'me', 'something', 'mydb');
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
if ($results = mysqli_query($dbc, $SQL))
{
etc...
PHP is so much faster that the Python scripts. I have to think developers must have noticed. I want to use Python going forward and I keep hearing that it is the way to do for so many big company websites. I have to assume...
- there is some magic setting either in Apache or Python to make the scripts start up faster (and this may be outside the scope of this group),
- and that there is some additional trick to make the database connections faster in the MySQL+Python system (which is the question that has led me to this group).
Any suggestions are welcome.