我现在在托管服务器上运行一个 mysql docker 容器镜像,具有 2 核 14gb ram 8000 iops max 我经常选择和更新查询
我确实使用 python 和 mysql-connector
我在开始时初始化一个连接 我在开始时打开连接的性能更好,并且 仅在退出时关闭它
def initsql():
logger.log('initsql()')
global cnx
cnx = mysql.connector.connect(user='blabla', password='blabla',
host='blablahost',
database='blablabladb')
def closesql():
logger.log('closesql()')
global cnx
cnx.close()
现在有 2 个非常慢的函数:
def sqlSetModus(modus):
logger.log('sqlSetModus()')
t0 = time.time()
try:
internet_on() #Function check if there is a internet connection if not raise Exception()
global cnx
cursor = cnx.cursor()
global logintoken
currentdate = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
if modus == 'offline':
updateModus = '''UPDATE accounts SET inuse=0, token='none', was_online = '%s', modus = '%s' WHERE token = '%s' ''' % (currentdate, modus, logintoken)
else:
updateModus = '''UPDATE accounts SET was_online = '%s', modus = '%s' WHERE token = '%s' ''' % (currentdate, modus, logintoken)
cursor.execute(updateModus)
cnx.commit()
logger.success("sqlSetModus after {} Sekunden".format(time.time() - t0))
return True
except Exception:
logger.error("Error sqlSetModus after {} Sekunden".format(time.time() - t0))
raise Exception
finally:
cursor.close()
def sqlUpdatePoints(company):
logger.log('sqlUpdatePoints()')
t0 = time.time()
try:
internet_on()
global cnx
cursor = cnx.cursor()
global sessiontoken
currentdate = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
pointsvalue = 0.55
updateOnline = '''UPDATE accounts SET was_online = '%s', this_points = this_points + '%s' WHERE token = '%s' ''' % (currentdate, pointsvalue, logintoken)
cursor.execute(updateOnline)
updatePoints = '''UPDATE points SET points = points + '%s' WHERE company = 'companyXYZ' ''' % (pointvalue,)
cursor.execute(updatePoints)
updateAccount = '''INSERT INTO statistic (company, datum, website) VALUES ('companyXYZ', '%s', '%s') ON DUPLICATE KEY UPDATE counter=counter+1''' % (currentdate, company)
cursor.execute(updateAccount)
cnx.commit()
logger.success("sqlSetAfterSuccesplay after {} Sekunden".format(time.time() - t0))
return True
except Exception:
logger.error("Error sqlSetAfterSuccesplay after {} Sekunden".format(time.time() - t0))
raise Exception
finally:
cursor.close()
我当然有更多的代码和更多的 sql 查询,比如简单的选择,但这些确实工作得很快
这两个函数的耗时总是超过 10 秒
sqlUpdatePoints 次:
[17:38:57.790] sqlUpdatePoints after 13.4862029552 Sekunden
[17:39:48.294] sqlUpdatePoints after 14.960242033 Sekunden
sqlSetModus 次:
[17:38:44.051] sqlSetModus after 14.4736759663 Sekunden
[17:39:31.702] sqlSetModus after 13.1622648239 Sekunden
[17:40:09.977] sqlSetModus after 16.7646770477 Sekunden
简单的选择查询时间:
[17:39:53.213] sqlGetActiveAccount after 0.741001844406 Sekunden
[17:39:02.695] sqlGetActiveAccount after 0.737174034119 Sekunden
[17:38:12.800] sqlGetActiveAccount after 0.7693400383 Sekunden
你必须知道我同时运行了 100 个此代码的实例,这意味着这些是打开 100 个连接的时间 并且经常对数据库运行 sqlUpdatePoints + sqlSetModus 和简单查询
- 我怎样才能加快查询速度。
- 如果我确实声明了好的主键/索引,速度会提高吗?如果是,什么应该是主键或索引。 我该如何设置它们?
表格看起来像这样:
nr = int (autoincrement unique)
username = varchar
password = varchar
inuse = int
token = varchar
was_online = datetime
points = float
modus = enum
nr | username | password | inuse | token | was_online | this_points | modus
最佳答案
你没有说你已经有哪些索引,所以我假设你没有:
对于
sqlSetModus()
函数,您需要索引:create index ix_account_token on accounts (token);
对于
sqlUpdatePoints()
函数,您需要索引:create index ix_points_company on points (company);
您对过滤器使用相等性 (=
),因此使用这些索引,您的搜索(更新)应该非常快。
关于Python MYSQL 查询太慢,请问是什么原因。用好的索引优化可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51329049/