mysql到旧的mariadb-性能较慢

6ljaweal  于 2021-06-18  发布在  Mysql
关注(0)|答案(3)|浏览(271)

所以我在从一个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的语句:

为更老、更快的数据库解释语句:

你知道还有什么要检查吗?我能做些什么来解决这个问题?
谢谢你的帮助

3z6pesqy

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 跨多个表。
以下是一些可能有帮助的综合索引:

pd:   INDEX(ID_sProduct, ID, stock)  -- perhaps this order is best
pdw:  INDEX(ID_sProductDetail, stock)  -- in this  order
pdsp: INDEX(ID_sProductDetail, memberPanCode, ID)  -- in this order
s:    INDEX(memberPanCode, shownOnSite)  -- in either order

另外,添加

p:  INDEX(showDate, published, ID, ID_sSupplier) -- in this order

并通过拉 p.* 离开主流。目前,笨重的p.*被拖过连接处等,然后缩减到只有3排。通过重组,我们可以先找到哪3行,然后获取所有内容:

SELECT p2.*, etc.
       p2.releaseDate > NOW() - INTERVAL 2 WEEK  AS pNew,
       etc.
    FROM (
        SELECT  toss p.*, add p.ID, keep other columns
            FROM ...
            LEFT JOIN ...
            ORDER BY...
            LIMIT 3
         ) AS x
    JOIN sProduct AS p2  ON x.ID = p2.ID
    ORDER BY p2.showDate desc

新的索引涵盖了 p 在子查询中是在索引中。我注意到了 releaseDate 第二次使用 sProduct .
我把 sShowDate 首先在索引中假设它至少做了一些过滤( p.showDate < NOW + INTERVAL 1 DAY ).
这个 GROUP BY 以及 ORDER BY 组合需要一个或两个文件序列;他们不能被消灭。我所做的是尽量减少他们的成本,使他们不那么笨重。

t5zmwmid

t5zmwmid2#

执行计划(在解释输出中显示)是不同的。因此,我们有理由期待不同的性能特征。
正如@rickjames在评论中指出的,目标环境中似乎缺少一些索引。
问题是:“两台服务器上的索引是相同的。”
但所提供的信息使我们得出结论,这些指数是不一样的。
我们看到在第一个解释的输出中引用了一些索引。在第二个解释的输出中找不到这些索引名。在模式定义脚本中也找不到这些索引名。
问:为什么模式定义中的一些索引(在第一个解释中报告的)丢失了?
问:是不是 mysqldump 是否修改了迁移的文件以删除某些索引定义?
问:是不是有别的工具 mysqldump 用于提取迁移的模式定义,是否省略了索引?
问:某些“createindex”语句在目标环境中执行失败了吗(可能是因为索引中列的大小受到限制?)
或者我有相反的方法,可能有一些添加到目标中的索引在源中不存在。

gjmwrych

gjmwrych3#

这个问题很难回答 WHERE 情况是不必要的复杂
原始查询(格式化)

SELECT p.*,
          pd.ID,
          detailID, /**include table alias? */
          s.title subject,
          s.displayTitle,
          s.memberPanCode,
          s.virtualDelivery,
          (p.releaseDate < NOW() - INTERVAL 2 WEEK) pNew /**Booleans are resolve to 1/0 in MySQL */
          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

     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)
          ) */ pd.ID > 0 /**see below */
      AND p.showDate < NOW() + INTERVAL 1 DAY 
      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

让我们从这个条件开始

AND (
         /**This with the last subcondition is just pd.ID > 0 */
         (pd.ID > 0 AND s.displayTitle IS NOT NULL)  

         /**This is impossible due to your INNER JOIN */
      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) 

         /**This with the first subcondition is just pd.ID > 0 */
      OR (pd.ID > 0 AND s.displayTitle IS NULL)
       )

整个情况都解决了 pd.ID > 0 ,除非您手动添加了id为0的产品,否则该值始终为真
我怀疑 (p.ID_sSupplier > 0 AND p.ID_sSupplier <> '3') 可以变得公正 p.ID_sSupplier <> 3 出于同样的原因
第一个条件似乎也非常包容

WHERE (
      s.publicChoice=1 
     OR s.defaultSubject=1 
     OR s.memberPanCode='' 
     OR s.memberPanCode IS NULL
      )  
   ...

这就引出了一个问题,在这种情况下,您实际上要避免哪些行?
GROUPBY子句也令人担忧,因为您没有选择聚合列。。你的最后一栏会被任意选择
你用这个查询到底想达到什么目的?
值得记住的是 OR 情况往往比正常情况更难解决 AND 使用查询时的条件

相关问题