使用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/