所以我在从一个web服务器到另一个web服务器的db迁移中遇到了问题。服务器1的MySQL5.6版本运行在cpanel托管下。。。服务器2有运行在webmin/virtualmin下的mariadb版本5.5,两者的php版本相同…5.6
无论如何,我想把一个站点从服务器1移到服务器2。我使用heidisql导出数据库,然后在服务器2上导入数据。导入的数据很好,但是查询的性能差了10倍。我检查了缓冲区大小变量和所有其他“键”变量,它们在服务器2上是相同的或增加的。我尝试将存储引擎从myisam改为aria或innodb,但结果是一样的……我还优化了整个db,但还是没有成功。两台服务器上的索引相同。
然后我决定把数据库放回原来的服务器上,然后从新服务器上加载文件……我导出了新的数据库(只使用insert ignore)并将sql导入到服务器1。导入后,原始数据库立即开始执行缓慢以及。。。除非我使用第一次移动数据库时的原始备份,否则无论我如何将数据库更新为新数据,它的性能都会很差。。。
现在运行查询需要35秒,而以前需要3秒:
select p.*, pd.ID detailID,
s.title subject, s.displayTitle, s.memberPanCode,
s.virtualDelivery,
CASE WHEN (DATE_ADD(p.releaseDate, INTERVAL 2 WEEK) > NOW()) THEN 1 ELSE 0 END pNew,
CASE WHEN(s.publicChoice=1) THEN s.memberPanCode ELSE '' END usableSubject,
CASE WHEN(s.displayTitle=1) THEN s.ID ELSE '0' END subjectID from sProduct p
inner join sProductDetail pd ON pd.ID_sProduct=p.ID
left join sProductDetailWarehouse pdw ON pdw.ID_sProductDetail=pd.ID
left join sProductDetailSubjectPrice pdsp ON pdsp.ID_sProductDetail=pd.ID
left join sSubject s ON (s.memberPanCode=pdsp.memberPanCode
and s.shownOnSite=1)
where ( s.publicChoice=1
OR s.defaultSubject=1
OR s.memberPanCode=''
OR s.memberPanCode IS NULL
)
AND ( (pd.ID > 0 AND s.displayTitle IS NOT NULL)
OR (pd.ID IS NULL AND s.displayTitle IS NULL )
OR (pd.ID > 0 and p.ID_sSupplier > 0 )
OR (pd.ID > 0 and pdsp.ID IS NULL )
OR (pd.ID > 0 and s.displayTitle IS NULL )
)
AND (DATE_ADD(NOW(), INTERVAL 1 DAY) > p.showDate)
AND ( pdw.stock > 0
OR pd.stock > 0
OR (p.ID_sSupplier > 0 AND p.ID_sSupplier <> '3')
)
and p.published IN (1,2)
GROUP BY p.ID, s.memberPanCode
order by p.showDate desc
limit 3
解释新的、较慢的db的语句:
为更老、更快的数据库解释语句:
你知道还有什么要检查吗?我能做些什么来解决这个问题?
谢谢你的帮助
3条答案
按热度按时间3z6pesqy1#
table有多大?innodb现在做到了
FULLTEXT
. 米桑成了孤儿。我同意不要用像5.5那么旧的东西。mariadb有10.0,10.1,10.2,10.3。mysql有5.6、5.7、8.0版本。其中大部分都做了大量的优化工作。回溯到5.5,可能会丢失一些优化特性。唉,我还没有发现丢失的具体东西。这个
ORs
对性能来说是致命的。它们基本上阻止了索引的使用。我看不到任何明显的方法来重新安排事情——因为ORs
跨多个表。以下是一些可能有帮助的综合索引:
另外,添加
并通过拉
p.*
离开主流。目前,笨重的p.*被拖过连接处等,然后缩减到只有3排。通过重组,我们可以先找到哪3行,然后获取所有内容:新的索引涵盖了
p
在子查询中是在索引中。我注意到了releaseDate
第二次使用sProduct
.我把
sShowDate
首先在索引中假设它至少做了一些过滤(p.showDate < NOW + INTERVAL 1 DAY
).这个
GROUP BY
以及ORDER BY
组合需要一个或两个文件序列;他们不能被消灭。我所做的是尽量减少他们的成本,使他们不那么笨重。t5zmwmid2#
执行计划(在解释输出中显示)是不同的。因此,我们有理由期待不同的性能特征。
正如@rickjames在评论中指出的,目标环境中似乎缺少一些索引。
问题是:“两台服务器上的索引是相同的。”
但所提供的信息使我们得出结论,这些指数是不一样的。
我们看到在第一个解释的输出中引用了一些索引。在第二个解释的输出中找不到这些索引名。在模式定义脚本中也找不到这些索引名。
问:为什么模式定义中的一些索引(在第一个解释中报告的)丢失了?
问:是不是
mysqldump
是否修改了迁移的文件以删除某些索引定义?问:是不是有别的工具
mysqldump
用于提取迁移的模式定义,是否省略了索引?问:某些“createindex”语句在目标环境中执行失败了吗(可能是因为索引中列的大小受到限制?)
或者我有相反的方法,可能有一些添加到目标中的索引在源中不存在。
gjmwrych3#
这个问题很难回答
WHERE
情况是不必要的复杂原始查询(格式化)
让我们从这个条件开始
整个情况都解决了
pd.ID > 0
,除非您手动添加了id为0的产品,否则该值始终为真我怀疑
(p.ID_sSupplier > 0 AND p.ID_sSupplier <> '3')
可以变得公正p.ID_sSupplier <> 3
出于同样的原因第一个条件似乎也非常包容
这就引出了一个问题,在这种情况下,您实际上要避免哪些行?
GROUPBY子句也令人担忧,因为您没有选择聚合列。。你的最后一栏会被任意选择
你用这个查询到底想达到什么目的?
值得记住的是
OR
情况往往比正常情况更难解决AND
使用查询时的条件