某些表条件下 MySQL/MariaDB 查询慢的可能原因

Nik*_*a 웃 6 mysql database database-performance mariadb

在某些条件下,我遇到了一个与慢速查询有关的奇怪问题:我进行了一些测试,并且能够将问题隔离到一个名为的单个表products_description(所有表都是 MyISAM)。起初我注意到当这个表是新的(即刚刚导入)时,查询总是执行得很快(~0.3s)。但是,如果我在此特定表上执行任何这些操作,则在任何时间(甚至在导入后立即执行): CHECK, OPTIMIZE,ANALYZEREPAIR,查询都会突然减慢 x10 倍(大约需要 4.5 秒)并且始终保持缓慢。

请注意,我在运行查询时强制无缓存以确保结果正确。

只有当我在该表上执行以下任何操作时,我才能恢复性能:

1)DROP表并再次导入。

或者

2)ALTER该表中的以下任何一项:CollationCHECKSUMDELAY_KEY_WRITE。然后它以更改的值快速运行,当恢复到旧值时,性能保持快速。或者ALTER products_description FORCE可以执行以恢复性能。

即便如此,如果我对该表执行任何CHECK, OPTIMIZE,ANALYZEREPAIR操作,查询速度会下降,直到我执行 1) 或 2)

我测试的另一件事:在对表执行任何操作之前,我备份了表的文件 ( products_description.frm, products_description.MYD, products_description.MYI),运行查询,它运行得很快。然后我CHECK在表上执行,运行查询,速度慢了 10 倍,我复制了备份文件并覆盖了 3 个文件,再次运行查询,再次降低速度。

我已经将数据库压缩到了一个 ~5mb 的 zip 文件中(解压缩了 ~80mb)。如果有人想在您自己的环境中测试数据库,请告诉我,我会向您发送下载链接。我可以在几个不同的服务器上重现这个,在 MariaDB 10.1+ 和 MySQL 5.6+ 上。

这是我正在运行的 SQL 查询,您应该使用以下命令进行测试:

SELECT DISTINCT pav.products_options_values_id, 
            pav.products_options_values_name, 
            pav.products_options_values_sort_order 
FROM   products_stock ps, 
       products_options_values pav, 
       (SELECT DISTINCT pa.products_id 
        FROM   products_attributes pa, 
               products_options_values pov, 
               (SELECT p.products_id, 
                       p.products_image, 
                       p.products_subimage1, 
                       pd.products_name, 
                       p.products_quantity, 
                       p.products_model, 
                       p.products_ordered, 
                       p.products_price, 
                       p.products_date_added, 
                       p.products_weight, 
                       p.products_length, 
                       p.products_width, 
                       p.products_height, 
                       p.products_tax_class_id, 
                       p.products_status, 
                       IF(s.status, s.specials_new_products_price, NULL) 
                       AS 
                       specials_new_products_price, 
                       IF(s.status, s.specials_new_products_price, 
                       p.products_price) AS 
                       final_price, 
                       IF(p.clearance_price < p.products_cost * 2.25, 
                       p.clearance_price, 
                       p.products_cost * 2.25) 
                       AS 
                       sorting_price 
                FROM   products p 
                       LEFT JOIN specials s 
                              ON p.products_id = s.products_id 
                       LEFT JOIN products_description pd 
                              ON p.products_id = pd.products_id 
                WHERE 
                 /*FASTIDS*/ 
                 p.products_status = '1' 
                 AND Date_sub('2016-04-19', INTERVAL 7000 day) <= 
                     p.products_date_added 
               ) m 
        WHERE  m.products_id = pa.products_id 
               AND pa.options_id = 1 
               AND pa.options_values_id = pov.products_options_values_id 
               AND pov.language_id = '1') q 
WHERE  q.products_id = ps.products_id 
       AND ps.products_stock_attributes = 
           Concat('1-', pav.products_options_values_id) 
       AND ps.products_stock_quantity > 0 
ORDER  BY pav.products_options_values_sort_order ASC 
Run Code Online (Sandbox Code Playgroud)

这是 EXPLAIN EXTENDED 结果。似乎优化器在两个表上的工作方式不同,但这并不能真正解释为什么会发生这种情况,因为复制的数据库应该是相同的。

慢数据库的解释

快速数据库的解释

这些是在慢速和快速数据库上分析查询的屏幕截图:

缓慢的数据库分析 快速数据库分析

造成这种巨大差异的可能原因是什么?如何验证和修复它们?

编辑: 根据评论中的要求,这些是显示表:

CREATE TABLE IF NOT EXISTS `products` (
  `products_id` int(11) NOT NULL AUTO_INCREMENT,
  `products_quantity` int(4) NOT NULL DEFAULT '0',
  `products_model` bigint(20) DEFAULT NULL,
  `products_image` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_med` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_lrg` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_sm_1` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_xl_1` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_sm_2` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_xl_2` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_sm_3` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_xl_3` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_sm_4` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_xl_4` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_sm_5` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_xl_5` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_sm_6` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_image_xl_6` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_bimage` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_subimage1` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_bsubimage1` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_subimage2` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_bsubimage2` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_subimage3` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_bsubimage3` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_subimage4` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_bsubimage4` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_subimage5` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_bsubimage5` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_subimage6` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_bsubimage6` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_price` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `clearance_price` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_cost` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_rmb_cost` decimal(7,2) DEFAULT NULL,
  `products_best_rmb` decimal(7,2) DEFAULT NULL,
  `products_thb_flag` tinyint(1) NOT NULL DEFAULT '0',
  `products_date_added` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `products_last_modified` datetime DEFAULT NULL,
  `products_date_available` datetime DEFAULT NULL,
  `products_weight` decimal(5,2) NOT NULL DEFAULT '0.00',
  `products_length` decimal(5,2) NOT NULL DEFAULT '0.00',
  `products_width` decimal(5,2) DEFAULT '0.00',
  `products_height` decimal(5,2) DEFAULT '0.00',
  `products_status` tinyint(1) NOT NULL DEFAULT '0',
  `products_tax_class_id` int(11) NOT NULL DEFAULT '0',
  `manufacturers_id` int(11) DEFAULT NULL,
  `products_ordered` int(11) NOT NULL DEFAULT '0',
  `products_parent_id` int(11) NOT NULL DEFAULT '0',
  `products_price1` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_price2` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_price3` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_price4` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_price5` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_price6` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_price7` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_price8` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_price9` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_price10` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_price11` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_price1_qty` int(11) NOT NULL DEFAULT '0',
  `products_price2_qty` int(11) NOT NULL DEFAULT '0',
  `products_price3_qty` int(11) NOT NULL DEFAULT '0',
  `products_price4_qty` int(11) NOT NULL DEFAULT '0',
  `products_price5_qty` int(11) NOT NULL DEFAULT '0',
  `products_price6_qty` int(11) NOT NULL DEFAULT '0',
  `products_price7_qty` int(11) NOT NULL DEFAULT '0',
  `products_price8_qty` int(11) NOT NULL DEFAULT '0',
  `products_price9_qty` int(11) NOT NULL DEFAULT '0',
  `products_price10_qty` int(11) NOT NULL DEFAULT '0',
  `products_price11_qty` int(11) NOT NULL DEFAULT '0',
  `products_qty_blocks` int(11) NOT NULL DEFAULT '1',
  `products_group_access` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'G,0',
  `products_nav_access` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'G,0',
  `sort_order` smallint(3) NOT NULL DEFAULT '0',
  `vendors_id` int(11) DEFAULT '1',
  `vendors_product_price` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `vendors_prod_id` varchar(24) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `vendors_prod_comments` mediumtext COLLATE utf8_unicode_ci,
  `products_qty_days` smallint(4) NOT NULL DEFAULT '0',
  `products_qty_years` smallint(4) NOT NULL DEFAULT '0',
  `products_quantity_order_min` int(8) NOT NULL DEFAULT '1',
  `products_quantity_order_units` int(8) NOT NULL DEFAULT '1',
  `products_price_list` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_price_rebate` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_discount1` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_discount2` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_discount3` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_discount4` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `products_discount1_qty` int(6) NOT NULL DEFAULT '0',
  `products_discount2_qty` int(6) NOT NULL DEFAULT '0',
  `products_discount3_qty` int(6) NOT NULL DEFAULT '0',
  `products_discount4_qty` int(6) NOT NULL DEFAULT '0',
  `products_discounts_id` int(11) NOT NULL DEFAULT '0',
  `products_priced_by_attribute` tinyint(1) NOT NULL DEFAULT '0',
  `product_is_free` tinyint(1) NOT NULL DEFAULT '0',
  `product_is_call` tinyint(1) NOT NULL DEFAULT '0',
  `products_quantity_mixed` tinyint(1) NOT NULL DEFAULT '0',
  `product_is_showroom_only` tinyint(1) NOT NULL DEFAULT '0',
  `products_discount_percentage` tinyint(1) NOT NULL DEFAULT '0',
  `products_price_excluded` tinyint(1) NOT NULL DEFAULT '0',
  `products_showhide` tinyint(1) NOT NULL DEFAULT '1',
  `products_group` varchar(11) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_vendor_code` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_comments` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_customers_approved` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`products_id`),
  KEY `idx_products_date_added` (`products_date_added`),
  KEY `products_model` (`products_model`),
  KEY `idx_products_customers_approved` (`products_customers_approved`),
  KEY `idx_products_status` (`products_status`),
  KEY `idx_products_price` (`products_price`),
  KEY `products_thb_flag` (`products_thb_flag`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=97489 ;

CREATE TABLE IF NOT EXISTS `products_attributes` (
  `products_attributes_id` int(11) NOT NULL AUTO_INCREMENT,
  `products_id` int(11) NOT NULL DEFAULT '0',
  `options_id` int(11) NOT NULL DEFAULT '0',
  `options_values_id` int(11) NOT NULL DEFAULT '0',
  `options_values_price` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `price_prefix` char(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `products_options_sort_order` smallint(3) unsigned NOT NULL DEFAULT '9999',
  `product_attribute_is_free` tinyint(1) NOT NULL DEFAULT '0',
  `products_attributes_weight` decimal(8,4) NOT NULL DEFAULT '0.0000',
  `products_attributes_weight_prefix` char(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `attributes_price_onetime` decimal(15,4) NOT NULL DEFAULT '0.0000',
  `attributes_display_only` tinyint(1) NOT NULL DEFAULT '0',
  `attributes_default` tinyint(1) NOT NULL DEFAULT '0',
  `attributes_qty_prices_onetime` mediumtext COLLATE utf8_unicode_ci,
  `attributes_discounted` tinyint(1) NOT NULL DEFAULT '1',
  `attributes_price_factor` decimal(8,2) NOT NULL DEFAULT '0.00',
  `attributes_price_factor_offset` decimal(8,2) NOT NULL DEFAULT '0.00',
  PRIMARY KEY (`products_attributes_id`),
  KEY `idx_products_attributes_products_id` (`products_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=57106 ;

CREATE TABLE IF NOT EXISTS `products_description` (
  `products_id` int(11) NOT NULL AUTO_INCREMENT,
  `language_id` int(11) NOT NULL DEFAULT '1',
  `products_name` varchar(160) COLLATE utf8_unicode_ci NOT NULL,
  `products_blurb` mediumtext COLLATE utf8_unicode_ci,
  `products_description` mediumtext COLLATE utf8_unicode_ci,
  `products_url` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_viewed` int(5) DEFAULT '0',
  `products_head_title_tag` varchar(80) COLLATE utf8_unicode_ci DEFAULT NULL,
  `products_head_desc_tag` longtext COLLATE utf8_unicode_ci,
  `products_head_keywords_tag` longtext COLLATE utf8_unicode_ci,
  `products_seo_url` varchar(100) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`products_id`,`language_id`),
  KEY `products_name` (`products_name`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=97489 ;

CREATE TABLE IF NOT EXISTS `products_options_values` (
  `products_options_values_id` int(11) NOT NULL DEFAULT '0',
  `language_id` int(11) NOT NULL DEFAULT '1',
  `products_options_values_name` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `products_options_values_sort_order` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`products_options_values_id`,`language_id`),
  KEY `products_options_values` (`products_options_values_sort_order`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE IF NOT EXISTS `products_stock` (
  `products_stock_id` int(11) NOT NULL AUTO_INCREMENT,
  `products_id` int(11) NOT NULL DEFAULT '0',
  `products_stock_attributes` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `products_stock_quantity` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`products_stock_id`),
  UNIQUE KEY `idx_products_stock_attributes` (`products_id`,`products_stock_attributes`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=57375 ;
Run Code Online (Sandbox Code Playgroud)

小智 5

显然,您已经在 MySQL/MariaDB 引擎和/或优化器中发现了一个相当严重的错误。

MariaDB 工作人员 (Elena Stepanova) 已报告(向 Oracle 和 Maria)报告并复制(确认)此错误,他们已将其分配给他们的一位主要开发人员(Sergei Petrunia)。我相信它可能会很快得到修复,因为 MariaDB 的人似乎工作效率很高。

有了 Oracle,好吧,完全不同的故事......

正如您发布的那样,您已经找到了临时解决方法,例如运行ALTER table FORCE. 做得好!