簡體   English   中英

5.7版與5.6版的MySQL性能

[英]MySQL performance for version 5.7 vs. 5.6

我注意到我不確定如何處理特定的性能問題。

我正在將Web應用程序從一台服務器遷移到具有非常相似規范的另一台服務器。 通常,新服務器的性能要優於舊服務器。

舊服務器正在運行MySQL 5.6.35
新服務器正在運行MySQL 5.7.17

新服務器和舊服務器實際上都具有相同的MySQL配置。 新服務器和舊服務器都運行完全相同的完全相同的數據庫。

有問題的Web應用程序是Magento 1.9.3.2。

在Magento中,以下函數Mage_Catalog_Model_Category::getChildrenCategories()旨在列出給定類別的所有直接子類別。

就我而言,此函數最終會涉及以下查詢:

SELECT    `main_table`.`entity_id`
        , main_table.`name`
        , main_table.`path`
        , `main_table`.`is_active`
        , `main_table`.`is_anchor`
        , `url_rewrite`.`request_path`

FROM `catalog_category_flat_store_1` AS `main_table`

LEFT JOIN `core_url_rewrite` AS `url_rewrite`
ON url_rewrite.category_id=main_table.entity_id
AND url_rewrite.is_system=1
AND url_rewrite.store_id = 1
AND url_rewrite.id_path LIKE 'category/%'

WHERE (main_table.include_in_menu = '1')
AND (main_table.is_active = '1')
AND (main_table.path LIKE '1/494/%')
AND (`level` <= 2)
ORDER BY `main_table`.`position` ASC;

盡管此查詢的結構對於任何Magento安裝都是相同的,但是在Magento安裝到Magento安裝與該功能所查看的類別之間的值顯然會略有差異。

我的catalog_category_flat_store_1表有214行。
我的url_rewrite表有1,734,316行。

直接在MySQL中單獨執行時,此查詢在MySQL版本之間的執行方式有很大不同。

我正在使用SQLyog來分析此查詢。

在MySQL 5.6中,以上查詢將在0.04秒內執行。 該查詢的配置文件如下所示: https : //codepen.io/Petce/full/JNKEpy/

在MySQL 5.7中,以上查詢在1.952秒內執行。 該查詢的配置文件如下所示: https : //codepen.io/Petce/full/gWMgKZ/

如您所見,幾乎完全相同的設置上的相同查詢實際上要慢2秒,我不確定原因。

由於某些原因,MySQL 5.7不想使用表索引來幫助生成結果集。

任何有更多經驗/知識的人都可以解釋這里發生了什么以及如何解決它?

我認為該問題與MYSQL 5.7優化器的工作方式有關。 出於某種原因,似乎認為全表掃描是必經之路。 我可以通過將max_seeks_for_key設置得非常低(例如100)或將range_optimizer_max_mem_size設置得非常低以強制其發出警告來大大提高查詢性能。

進行這兩種操作都會使查詢速度降低近10倍,降至0.2秒,但是,這要比在0.04秒內執行的MySQL 5.6慢很多,而且我認為這都不是一個好主意,因為我不是確定是否還會有其他影響。

修改查詢也是非常困難的,因為它是由Magento框架生成的,並且需要自定義Magento代碼庫,我想避免這種情況。 我也不確定這是否是唯一的查詢。

我已經為我的MySQL安裝提供了次要版本。 我現在正在嘗試將MySQL 5.7.17更新到5.7.18(最新版本),以查看性能是否有任何更新。

升級到MySQL 5.7.18之后,我看不到任何改善。 為了使系統恢復到穩定的高性能狀態,我們決定降級到MySQL 5.6.30。 降級后,我們看到了即時的改進。

以上查詢是在MySQL 5.6.30中在0.036秒內在NEW服務器上執行的。

哇! 這是我第一次從剖析中看到有用的東西。 動態創建索引是Oracle的一項新的優化功能。 但這似乎不是針對此案的最佳計划。

首先,我建議您在http://bugs.mysql.com上提交一個錯誤-他們不喜歡回歸,尤其是這種令人討厭的回歸。 如果可能,請提供EXPLAIN FORMAT=JSON SELECT...和“ Optimizer trace”。 (我不接受調整模糊的可調參數作為可接受的答案,但是感謝您發現它們。)

回到幫助您...

  • 如果不需要LEFT ,請不要使用它。 當“正確的”表中沒有匹配的行時,它將返回NULLs 你會發生這種情況嗎?
  • 請提供SHOW CREATE TABLE 同時,我猜您沒有INDEX(include_in_menu, is_active, path) 前兩個可以任意順序排列。 path必須是最后一條。
  • 最后是INDEX(category_id, is_system, store_id, id_path)id_path
  • 您的查詢似乎具有一種模式,可以很好地轉換為子查詢:

(注意:這甚至保留了LEFT的語義。)

SELECT  `main_table`.`entity_id` , main_table.`name` , main_table.`path` ,
        `main_table`.`is_active` , `main_table`.`is_anchor` ,
        ( SELECT  `request_path`
            FROM  url_rewrite
            WHERE  url_rewrite.category_id=main_table.entity_id
              AND  url_rewrite.is_system = 1
              AND  url_rewrite.store_id  = 1
              AND  url_rewrite.id_path LIKE 'category/%' 
        ) as request_path
    FROM  `catalog_category_flat_store_1` AS `main_table`
    WHERE  (main_table.include_in_menu = '1')
      AND  (main_table.is_active = '1')
      AND  (main_table.path like '1/494/%')
      AND  (`level` <= 2)
    ORDER BY  `main_table`.`position` ASC
    LIMIT  0, 1000 

(建議的索引也適用於此。)

這不是回答@Nigel Ren的唯一答案

在這里您可以看到LIKE也使用索引。

mysql> SELECT *
    -> FROM testdb
    -> WHERE
    -> vals LIKE 'text%';
+----+---------------------------------------+
| id | vals                                  |
+----+---------------------------------------+
|  3 | text for line number 3                |
|  1 | textline 1 we rqwe rq wer qwer q wer  |
|  2 | textline 2 asdf asd fas f asf  wer 3  |
+----+---------------------------------------+
3 rows in set (0,00 sec)

mysql> EXPLAIN
    -> SELECT *
    -> FROM testdb
    -> WHERE
    -> vals LIKE 'text%';
+----+-------------+--------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+
| id | select_type | table  | partitions | type  | possible_keys | key  | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+--------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | testdb | NULL       | range | vals          | vals | 515     | NULL |    3 |   100.00 | Using where; Using index |
+----+-------------+--------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0,01 sec)

mysql>

用LEFT()采樣

mysql> SELECT *
    -> FROM testdb
    -> WHERE
    -> LEFT(vals,4) = 'text';
+----+---------------------------------------+
| id | vals                                  |
+----+---------------------------------------+
|  3 | text for line number 3                |
|  1 | textline 1 we rqwe rq wer qwer q wer  |
|  2 | textline 2 asdf asd fas f asf  wer 3  |
+----+---------------------------------------+
3 rows in set (0,01 sec)

mysql> EXPLAIN
    -> SELECT *
    -> FROM testdb
    -> WHERE
    -> LEFT(vals,4) = 'text';
+----+-------------+--------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+
| id | select_type | table  | partitions | type  | possible_keys | key  | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+--------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | testdb | NULL       | index | NULL          | vals | 515     | NULL |    5 |   100.00 | Using where; Using index |
+----+-------------+--------+------------+-------+---------------+------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0,01 sec)

mysql>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM