使用Python MySQLdb从大表中获取数据时,我的执行时间非常长(而不是较长的获取时间),我想知道是否有任何明显错误的地方。

我的表定义如下:

create table mytable(
  a varchar(3),
  b bigint,
  c int,
  d int,
  e datetime,
  f varchar(20),
  g varchar(10),
  primary key(a, b, c, d))
ENGINE=InnoDB;


它当前包含1.5亿行,表大小估计为19GB。

Python代码如下:

import MySQLdb
database = MySQLdb.connect(passwd="x", host="dbserver", user="user", db="database", port=9999)
mysql_query = """select a, b, c, d, e, f, g from mytable use index (primary) where a = %s order by a, b, c, d"""
mysql_cursor = database.cursor()
mysql_cursor.execute(mysql_query, ["AA"])
for a, b, c, d, e, f, g in mysql_cursor:
    #Do something


我的惊喜来自于execute命令所花费的时间。尽管我本来希望execute几乎不花时间(因为它应该使用主键遍历表),并且在for循环中花费相当长的时间,但它在这里花费了很多时间。

解释计划如下:

explain select a, b, c, d, e, f, g from mytable use index (primary) where a = %s order by a, b, c, d
'1','SIMPLE','eventindex','ref','PRIMARY','PRIMARY','5','const','87402369','Using where'


此刻,所有行在a列中都包含相同的值(我后来想到要添加其他值,但此刻a内容的分布并不真正平衡)。 b列分布更好

有什么能解释MySQL在执行查询上花费大量时间(而不是花时间去获取行)?

奖金问题。优化该用例有明显的捷径吗?在b列上对表进行分区?列a?删除列a,并使用单独的表?

最佳答案

实际上看起来实际上像是一个MySQL问题-我认为问题与Python或mysql-python无关。

wrt / SQL内容:索引的选择性不够好(具有太多相似的值)可能会非常有害,因为除了索引树遍历之外,您还会进行顺序扫描-实际上,与普通表扫描相比,磁盘访问量更多- ,因此双方都松了手(IOW:您只会得到遍历索引树的开销,但没有好处)。您可以在以下位置找到更多相关信息:MySQL: low cardinality/selectivity columns = how to index?和此处Role of selectivity in index scan/seek

在您的情况下,您可能想尝试不带use index子句的查询,甚至可能迫使优化器改用ignore index clause普通绕过索引。

关于python - Python MySQLdb执行缓慢,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40400499/

10-11 03:07
查看更多