MySQL - 慢速查询优化
MySQL - slow query optimisation
我在优化一个非常慢的 prestashop SQL 查询时遇到问题(mysql 需要超过 2 秒才能得到结果)。
查询
SELECT SQL_CALC_FOUND_ROWS a.`id_order`,
`reference`,
`total_paid_tax_incl`,
`payment`,
a.`date_add` AS `date_add`,
a.id_currency,
a.id_order AS id_pdf,
CONCAT(LEFT(c.`firstname`, 1), '. ', c.`lastname`) AS `customer`,
osl.`name` AS `osname`,
os.`color`,
carrier.`name` AS `carriername`,
country_lang.name as cname,
IF(a.valid, 1, 0) badge_success,
shop.name as shop_name
FROM `ps_orders` a
LEFT JOIN `ps_customer` c ON (c.`id_customer` = a.`id_customer`)
INNER JOIN `ps_address` address ON address.id_address = a.id_address_delivery
INNER JOIN `ps_country` country ON address.id_country = country.id_country
INNER JOIN `ps_country_lang` country_lang
ON (country.`id_country` = country_lang.`id_country` AND country_lang.`id_lang` = 2)
INNER JOIN `ps_carrier` carrier ON (carrier.`id_carrier` = a.`id_carrier`)
LEFT JOIN `ps_order_state` os ON (os.`id_order_state` = a.`current_state`)
LEFT JOIN `ps_order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = 2)
LEFT JOIN `ps_shop` shop ON a.`id_shop` = shop.`id_shop`
WHERE 1
AND a.id_shop IN (1, 5, 3, 4)
ORDER BY a.id_order DESC
LIMIT 0, 50;
说明结果
CREATE TABLE `ps_orders` (
`id_order` int(10) unsigned NOT NULL AUTO_INCREMENT,
`reference` varchar(9) DEFAULT NULL,
`id_shop_group` int(11) unsigned NOT NULL DEFAULT '1',
`id_shop` int(11) unsigned NOT NULL DEFAULT '1',
`id_carrier` int(10) unsigned NOT NULL,
`id_lang` int(10) unsigned NOT NULL,
`id_customer` int(10) unsigned NOT NULL,
`id_cart` int(10) unsigned NOT NULL,
`id_currency` int(10) unsigned NOT NULL,
`id_address_delivery` int(10) unsigned NOT NULL,
`id_address_invoice` int(10) unsigned NOT NULL,
`current_state` int(10) unsigned NOT NULL,
`secure_key` varchar(32) NOT NULL DEFAULT '-1',
`payment` varchar(255) NOT NULL,
`conversion_rate` decimal(13,6) NOT NULL DEFAULT '1.000000',
`module` varchar(255) DEFAULT NULL,
`recyclable` tinyint(1) unsigned NOT NULL DEFAULT '0',
`gift` tinyint(1) unsigned NOT NULL DEFAULT '0',
`gift_message` text,
`mobile_theme` tinyint(1) NOT NULL DEFAULT '0',
`shipping_number` varchar(64) DEFAULT NULL,
`total_discounts` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_discounts_tax_incl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_discounts_tax_excl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_paid` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_paid_tax_incl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_paid_tax_excl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_paid_real` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_products` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_products_wt` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_shipping` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_shipping_tax_incl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_shipping_tax_excl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`carrier_tax_rate` decimal(10,3) NOT NULL DEFAULT '0.000',
`total_wrapping` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_wrapping_tax_incl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_wrapping_tax_excl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`round_mode` tinyint(1) NOT NULL DEFAULT '2',
`round_type` tinyint(1) NOT NULL DEFAULT '1',
`invoice_number` int(10) unsigned NOT NULL DEFAULT '0',
`delivery_number` int(10) unsigned NOT NULL DEFAULT '0',
`invoice_date` datetime NOT NULL,
`delivery_date` datetime NOT NULL,
`valid` int(1) unsigned NOT NULL DEFAULT '0',
`date_add` datetime NOT NULL,
`date_upd` datetime NOT NULL,
`client_message` text,
`ac_processed` tinyint(1) DEFAULT '0',
`twilio` tinyint(1) DEFAULT NULL,
`stop_sync` int(1) NOT NULL DEFAULT '0',
`moloni_internal` tinyint(1) DEFAULT '0',
`moloni_offers` tinyint(1) DEFAULT '0',
`bonus_credited_at` datetime DEFAULT NULL,
`feedback_survey_sent_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id_order`),
KEY `reference` (`reference`),
KEY `id_customer` (`id_customer`),
KEY `id_cart` (`id_cart`),
KEY `invoice_number` (`invoice_number`),
KEY `id_carrier` (`id_carrier`),
KEY `id_lang` (`id_lang`),
KEY `id_currency` (`id_currency`),
KEY `id_address_delivery` (`id_address_delivery`),
KEY `id_address_invoice` (`id_address_invoice`),
KEY `id_shop_group` (`id_shop_group`),
KEY `current_state` (`current_state`),
KEY `id_shop` (`id_shop`),
KEY `date_add` (`date_add`)
) ENGINE=InnoDB AUTO_INCREMENT=185578 DEFAULT CHARSET=utf8
我发现如果我同时删除 SQL_CALC_FOUNDS_ROWS 和 order by 子句,执行时间会从 2 秒减少到 250 毫秒。
这是来自 Prestashop 的查询...不确定我是否可以删除 SQL_CALC_FOUND_ROWS 以及会有什么影响。
如何优化此查询?
这是否给出了正确的计数?
SELECT COUNT(*) FROM a
WHERE a.id_shop IN (1, 5, 3, 4)
如果是,则使用 代替 SELECT FOUND_ROWS()
的 。
这是否为您提供了您想要的 a
行?
SELECT a.id FROM a
WHERE a.id_shop IN (1, 5, 3, 4)
ORDER BY a.id_order DESC
LIMIT 0, 50;
将这两个索引添加到a
:
INDEX(id_shop, id_order),
INDEX(id_order)
在合理的时间内完成上述查询运行?
如果是,则执行类似
的操作
SELECT ...
FROM ( the query above, with the ORDER BY and LIMIT )
JOIN a USING(id) -- "self join"
and the rest of the joins
ORDER BY a.id_order DESC;
请提供SHOW CREATE TABLE ps_orders
文字,而非图片。
我在优化一个非常慢的 prestashop SQL 查询时遇到问题(mysql 需要超过 2 秒才能得到结果)。
查询
SELECT SQL_CALC_FOUND_ROWS a.`id_order`,
`reference`,
`total_paid_tax_incl`,
`payment`,
a.`date_add` AS `date_add`,
a.id_currency,
a.id_order AS id_pdf,
CONCAT(LEFT(c.`firstname`, 1), '. ', c.`lastname`) AS `customer`,
osl.`name` AS `osname`,
os.`color`,
carrier.`name` AS `carriername`,
country_lang.name as cname,
IF(a.valid, 1, 0) badge_success,
shop.name as shop_name
FROM `ps_orders` a
LEFT JOIN `ps_customer` c ON (c.`id_customer` = a.`id_customer`)
INNER JOIN `ps_address` address ON address.id_address = a.id_address_delivery
INNER JOIN `ps_country` country ON address.id_country = country.id_country
INNER JOIN `ps_country_lang` country_lang
ON (country.`id_country` = country_lang.`id_country` AND country_lang.`id_lang` = 2)
INNER JOIN `ps_carrier` carrier ON (carrier.`id_carrier` = a.`id_carrier`)
LEFT JOIN `ps_order_state` os ON (os.`id_order_state` = a.`current_state`)
LEFT JOIN `ps_order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = 2)
LEFT JOIN `ps_shop` shop ON a.`id_shop` = shop.`id_shop`
WHERE 1
AND a.id_shop IN (1, 5, 3, 4)
ORDER BY a.id_order DESC
LIMIT 0, 50;
说明结果
CREATE TABLE `ps_orders` (
`id_order` int(10) unsigned NOT NULL AUTO_INCREMENT,
`reference` varchar(9) DEFAULT NULL,
`id_shop_group` int(11) unsigned NOT NULL DEFAULT '1',
`id_shop` int(11) unsigned NOT NULL DEFAULT '1',
`id_carrier` int(10) unsigned NOT NULL,
`id_lang` int(10) unsigned NOT NULL,
`id_customer` int(10) unsigned NOT NULL,
`id_cart` int(10) unsigned NOT NULL,
`id_currency` int(10) unsigned NOT NULL,
`id_address_delivery` int(10) unsigned NOT NULL,
`id_address_invoice` int(10) unsigned NOT NULL,
`current_state` int(10) unsigned NOT NULL,
`secure_key` varchar(32) NOT NULL DEFAULT '-1',
`payment` varchar(255) NOT NULL,
`conversion_rate` decimal(13,6) NOT NULL DEFAULT '1.000000',
`module` varchar(255) DEFAULT NULL,
`recyclable` tinyint(1) unsigned NOT NULL DEFAULT '0',
`gift` tinyint(1) unsigned NOT NULL DEFAULT '0',
`gift_message` text,
`mobile_theme` tinyint(1) NOT NULL DEFAULT '0',
`shipping_number` varchar(64) DEFAULT NULL,
`total_discounts` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_discounts_tax_incl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_discounts_tax_excl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_paid` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_paid_tax_incl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_paid_tax_excl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_paid_real` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_products` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_products_wt` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_shipping` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_shipping_tax_incl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_shipping_tax_excl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`carrier_tax_rate` decimal(10,3) NOT NULL DEFAULT '0.000',
`total_wrapping` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_wrapping_tax_incl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`total_wrapping_tax_excl` decimal(20,6) NOT NULL DEFAULT '0.000000',
`round_mode` tinyint(1) NOT NULL DEFAULT '2',
`round_type` tinyint(1) NOT NULL DEFAULT '1',
`invoice_number` int(10) unsigned NOT NULL DEFAULT '0',
`delivery_number` int(10) unsigned NOT NULL DEFAULT '0',
`invoice_date` datetime NOT NULL,
`delivery_date` datetime NOT NULL,
`valid` int(1) unsigned NOT NULL DEFAULT '0',
`date_add` datetime NOT NULL,
`date_upd` datetime NOT NULL,
`client_message` text,
`ac_processed` tinyint(1) DEFAULT '0',
`twilio` tinyint(1) DEFAULT NULL,
`stop_sync` int(1) NOT NULL DEFAULT '0',
`moloni_internal` tinyint(1) DEFAULT '0',
`moloni_offers` tinyint(1) DEFAULT '0',
`bonus_credited_at` datetime DEFAULT NULL,
`feedback_survey_sent_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id_order`),
KEY `reference` (`reference`),
KEY `id_customer` (`id_customer`),
KEY `id_cart` (`id_cart`),
KEY `invoice_number` (`invoice_number`),
KEY `id_carrier` (`id_carrier`),
KEY `id_lang` (`id_lang`),
KEY `id_currency` (`id_currency`),
KEY `id_address_delivery` (`id_address_delivery`),
KEY `id_address_invoice` (`id_address_invoice`),
KEY `id_shop_group` (`id_shop_group`),
KEY `current_state` (`current_state`),
KEY `id_shop` (`id_shop`),
KEY `date_add` (`date_add`)
) ENGINE=InnoDB AUTO_INCREMENT=185578 DEFAULT CHARSET=utf8
我发现如果我同时删除 SQL_CALC_FOUNDS_ROWS 和 order by 子句,执行时间会从 2 秒减少到 250 毫秒。
这是来自 Prestashop 的查询...不确定我是否可以删除 SQL_CALC_FOUND_ROWS 以及会有什么影响。
如何优化此查询?
这是否给出了正确的计数?
SELECT COUNT(*) FROM a
WHERE a.id_shop IN (1, 5, 3, 4)
如果是,则使用 代替 SELECT FOUND_ROWS()
的 。
这是否为您提供了您想要的 a
行?
SELECT a.id FROM a
WHERE a.id_shop IN (1, 5, 3, 4)
ORDER BY a.id_order DESC
LIMIT 0, 50;
将这两个索引添加到a
:
INDEX(id_shop, id_order),
INDEX(id_order)
在合理的时间内完成上述查询运行?
如果是,则执行类似
的操作SELECT ...
FROM ( the query above, with the ORDER BY and LIMIT )
JOIN a USING(id) -- "self join"
and the rest of the joins
ORDER BY a.id_order DESC;
请提供SHOW CREATE TABLE ps_orders
文字,而非图片。