Python MYSQL 查询太慢,请问是什么原因。用好的索引优化可能吗?

标签 python mysql sql docker query-optimization

我现在在托管服务器上运行一个 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/

相关文章:

python - 类型错误 : not enough arguments for format string on my project

mysql - 如何在mysql中按小时汇总

c# - 在 SQL Server 中给定一行 n 个数字,我如何找到行的总和达到值 k 的点?

python - 根据python中的索引列表获取列表中的元素

Python无法分割数据帧时间戳错误

python - 如何将一个大数字拆分成单个数字?

python - 避免 Python 中的多个 Try/Except block

MySQL,检测排序索引上的行值更改

android - 如何在我的应用程序中组织 SQLite 数据库

sql - 在 SQL Server 2012 中选择逗号分隔值