我有这个问题让我疯狂了很长一段时间。它有3个表(最初它有更多,但我隔离了性能问题),1个基表,1个产品表添加更多数据,1个产品类型。 产品类型表包含"最大年龄"列,表示我想要获取的行的最大年龄(任何旧的都被认为是#34;存档"),并且其值根据产品类型而不同。 我糟糕的性能查询是这样的,250,000行基表需要50秒:
from pyspark.mllib.regression import LabeledPoint
import numpy as np
a = LabeledPoint(0, [1,2,3])
b = LabeledPoint(0, [3,1,2])
c = LabeledPoint(a.label, np.concatenate((a.features, b.features), axis=0))
print c # LabeledPoint(0.0, [1.0,2.0,3.0,3.0,1.0,2.0])
以下是此查询的EXPLAIN:
(select d_baseservices.ID
from d_baseservices
inner join d_products on d_baseservices.ServiceID = d_products.ServiceID
inner join md_prodtypes on d_products.ProdType = md_prodtypes.ProdType
where
(d_baseservices.CreationDate > (curdate() - INTERVAL md_prodtypes.MaxAge DAY))
order by CreationDate desc
limit 750);
几天前我发现了一条线索,当我能够确定将查询限制为750条记录会导致速度变快,但751会带来糟糕的表现。
我尝试创建多种索引,但没有成功。 我尝试删除对MAX_AGE和curdate函数的引用,只设置一个固定值,但由于查询现在需要20秒,因此收效甚微:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE md_prodtypes index PRIMARY,ProdType_UNIQUE,ID_MAX_AGE MAX_AGE 5 23 Using index; Using temporary; Using filesort
1 SIMPLE d_products ref PRIMARY,ServiceID_UNIQUE,fk_Products_BaseServices1,fk_d_products_md_prodtypes1 fk_d_products_md_prodtypes1 4 combina.md_prodtypes.ProdType 8625
1 SIMPLE d_baseservices eq_ref PRIMARY,CreationDateDesc_index,CreationDate_index PRIMARY 8 combina.d_products.ServiceID 1 Using where
并且EXPLAIN命令输出:
(select d_baseservices.ID
from d_baseservices
inner join d_products on d_baseservices.ServiceID = d_products.ServiceID
inner join md_prodtypes on d_products.ProdType = md_prodtypes.ProdType
where
(d_baseservices.CreationDate > '2015-09-21 19:02:25')
order by CreationDate desc
limit 750);
有人可以帮忙吗?我被困了将近一个月
答案 0 :(得分:2)
如果不了解更多有关您拥有的特定数据(每个表中有多少行,您希望查询返回多少行,数据值的分布等),很难确切地说要做什么),但我会做一些有根据的猜测,并希望指出你正确的方向。
首先解释为什么从查询中取出md_prodtypes.MaxAge
大大减少了运行时间:在更改之前,数据库根本没有能力使用索引进行过滤,因为为了查看行是否适合包含已加入这三个表,以便将第一个表中的CreationDate
与第三个表中的MaxAge
进行比较。您可以添加任何索引来关联这两个值。您强制数据库引擎查看每一行。
对于750幻数 - 我猜测过去750结果数据库必须分页数据,或者根据特定MySQL配置文件中的值来达到其他内存限制。我不会过多地读到那个750号码。
最后,我想指出你的第二个查询的EXPLAIN有点奇怪,因为它显示md_prodtypes
作为第一个表,尽管你已经{{1} } MaxAge
之外。这意味着数据库从WHERE
开始,然后向上移动到md_prodtypes
,最后到d_products
,然后根据日期进行过滤。我猜你是否期望它首先在日期过滤,然后只有当它决定要包括哪些baseservices记录时才加入。用你提供的信息知道为什么会发生这种情况是不可能的。也许你错过了一个索引
另一种可能性可能与您的d_baseservices
列中的差异有关。让我通过示例解释一下:假设您有一个用户表,每个用户都有一个CreationDate
列,可以是gender
或f
。让我们假设我们有50%/ 50%的女性和男性分开。现在,如果您在列m
上添加索引并执行由gender
过滤的查询,期望索引将过滤掉一半的记录,那么您会惊讶地看到该数据库将完全忽略索引并只扫描表。原因在于,如果您知道索引不足以过滤掉(替代方案是从索引到主表数据不断跳跃),那么读取整个表格会更便宜。在您的情况下,如果WHERE gender='f'
列上的WHERE没有过滤掉足够的记录,那么即使您有一个索引,它也不会被使用。
答案 1 :(得分:0)
日期不变......
INDEX(CreationDate)
这将鼓励优化器从可以过滤的表开始。此外,由于ORDER BY
位于同一字段,因此WHERE
,ORDER BY
和LIMIT
可以同时完成。
否则,它必须读取所有3个表中的所有相关记录,对它们进行排序,然后发送750(或751)个表。
使用MAX_AGE ...
现在优化器不会知道如上所述更好还是找到所有行,对它们进行排序,然后传递LIMIT。