繁体   English   中英

使用4个JOINS和优化MySQL查询

[英]Optimising MySQL query with 4 JOINS and

由于当前数据库崩溃,我需要尽可能优化MySQL查询。 我们有5张桌子:

  • 订单-包含约20万条记录
  • 语言-包含2-5
  • 记录order_product-包含超过20万条记录
  • 产品-包含少于100条记录
  • 新闻通讯-包含5万多条记录

当我们尝试通过电子邮件加入新闻稿表时,事情开始出错了。

这是每个的创建表:

CREATE TABLE `order` (
 `order_id` int(11) NOT NULL AUTO_INCREMENT,
 `order_id_copy` varchar(32) COLLATE utf8_bin NOT NULL,
 `invoice_no` int(11) NOT NULL DEFAULT '0',
 `invoice_prefix` varchar(26) COLLATE utf8_bin NOT NULL,
 `store_id` int(11) NOT NULL DEFAULT '0',
 `store_name` varchar(64) COLLATE utf8_bin NOT NULL,
 `store_url` varchar(255) COLLATE utf8_bin NOT NULL,
 `customer_id` int(11) NOT NULL DEFAULT '0',
 `customer_group_id` int(11) NOT NULL DEFAULT '0',
 `firstname` varchar(32) COLLATE utf8_bin NOT NULL DEFAULT '',
 `lastname` varchar(32) COLLATE utf8_bin NOT NULL,
 `email` varchar(96) COLLATE utf8_bin NOT NULL,
 `telephone` varchar(32) COLLATE utf8_bin NOT NULL DEFAULT '',
 `fax` varchar(32) COLLATE utf8_bin NOT NULL DEFAULT '',
 `payment_firstname` varchar(32) COLLATE utf8_bin NOT NULL DEFAULT '',
 `payment_lastname` varchar(32) COLLATE utf8_bin NOT NULL DEFAULT '',
 `payment_company` varchar(32) COLLATE utf8_bin NOT NULL,
 `payment_company_id` varchar(32) COLLATE utf8_bin NOT NULL,
 `payment_tax_id` varchar(32) COLLATE utf8_bin NOT NULL,
 `payment_address_1` varchar(128) COLLATE utf8_bin NOT NULL,
 `payment_address_2` varchar(128) COLLATE utf8_bin NOT NULL,
 `payment_city` varchar(128) COLLATE utf8_bin NOT NULL,
 `payment_postcode` varchar(10) COLLATE utf8_bin NOT NULL DEFAULT '',
 `payment_country` varchar(128) COLLATE utf8_bin NOT NULL,
 `payment_country_id` int(11) NOT NULL,
 `payment_zone` varchar(128) COLLATE utf8_bin NOT NULL,
 `payment_zone_id` int(11) NOT NULL,
 `payment_address_format` text COLLATE utf8_bin NOT NULL,
 `payment_method` varchar(128) COLLATE utf8_bin NOT NULL DEFAULT '',
 `payment_code` varchar(128) COLLATE utf8_bin NOT NULL,
 `shipping_firstname` varchar(32) COLLATE utf8_bin NOT NULL,
 `shipping_lastname` varchar(32) COLLATE utf8_bin NOT NULL DEFAULT '',
 `shipping_company` varchar(32) COLLATE utf8_bin NOT NULL,
 `shipping_address_1` varchar(128) COLLATE utf8_bin NOT NULL,
 `shipping_address_2` varchar(128) COLLATE utf8_bin NOT NULL,
 `shipping_city` varchar(128) COLLATE utf8_bin NOT NULL,
 `shipping_postcode` varchar(10) COLLATE utf8_bin NOT NULL DEFAULT '',
 `shipping_country` varchar(128) COLLATE utf8_bin NOT NULL,
 `shipping_country_id` int(11) NOT NULL,
 `shipping_zone` varchar(128) COLLATE utf8_bin NOT NULL,
 `shipping_zone_id` int(11) NOT NULL,
 `shipping_address_format` text COLLATE utf8_bin NOT NULL,
 `shipping_method` varchar(128) COLLATE utf8_bin NOT NULL DEFAULT '',
 `shipping_code` varchar(128) COLLATE utf8_bin NOT NULL,
 `comment` text COLLATE utf8_bin NOT NULL,
 `total` decimal(15,4) NOT NULL DEFAULT '0.0000',
 `order_status_id` int(11) NOT NULL DEFAULT '0',
 `affiliate_id` int(11) NOT NULL,
 `commission` decimal(15,4) NOT NULL,
 `language_id` int(11) NOT NULL,
 `currency_id` int(11) NOT NULL,
 `currency_code` varchar(3) COLLATE utf8_bin NOT NULL,
 `currency_value` decimal(15,8) NOT NULL DEFAULT '1.00000000',
 `ip` varchar(15) COLLATE utf8_bin NOT NULL,
 `forwarded_ip` varchar(15) COLLATE utf8_bin NOT NULL,
 `user_agent` varchar(255) COLLATE utf8_bin NOT NULL,
 `accept_language` varchar(255) COLLATE utf8_bin NOT NULL,
 `date_added` datetime NOT NULL,
 `date_modified` datetime NOT NULL,
 `newsletter` tinyint(1) NOT NULL DEFAULT '0',
 PRIMARY KEY (`order_id`),
 KEY `date_added` (`date_added`),
 KEY `date_modified` (`date_modified`),
 KEY `date_added_2` (`date_added`),
 KEY `store_id` (`store_id`),
 KEY `customer_id` (`customer_id`),
 KEY `customer_group_id` (`customer_group_id`),
 KEY `payment_company_id` (`payment_company_id`),
 KEY `payment_tax_id` (`payment_tax_id`),
 KEY `payment_country_id` (`payment_country_id`),
 KEY `payment_zone_id` (`payment_zone_id`),
 KEY `shipping_country_id` (`shipping_country_id`),
 KEY `shipping_zone_id` (`shipping_zone_id`),
 KEY `order_status_id` (`order_status_id`),
 KEY `affiliate_id` (`affiliate_id`),
 KEY `language_id` (`language_id`),
 KEY `currency_id` (`currency_id`)
) ENGINE=MyISAM AUTO_INCREMENT=421544 DEFAULT CHARSET=utf8 COLLATE=utf8_bin

CREATE TABLE `language` (
 `language_id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(32) NOT NULL,
 `code` varchar(5) NOT NULL,
 `locale` varchar(255) NOT NULL,
 `image` varchar(64) NOT NULL,
 `directory` varchar(32) NOT NULL,
 `filename` varchar(64) NOT NULL,
 `sort_order` int(3) NOT NULL DEFAULT '0',
 `status` tinyint(1) NOT NULL,
 PRIMARY KEY (`language_id`),
 KEY `name` (`name`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

CREATE TABLE `order_product` (
 `order_product_id` int(11) NOT NULL AUTO_INCREMENT,
 `order_id` int(11) NOT NULL,
 `product_id` int(11) NOT NULL,
 `name` varchar(255) COLLATE utf8_bin NOT NULL,
 `model` varchar(24) COLLATE utf8_bin NOT NULL,
 `quantity` int(4) NOT NULL,
 `price` decimal(15,4) NOT NULL DEFAULT '0.0000',
 `total` decimal(15,4) NOT NULL DEFAULT '0.0000',
 `tax` decimal(15,4) NOT NULL DEFAULT '0.0000',
 `discount` decimal(15,4) NOT NULL,
 `discount_tax` decimal(15,4) NOT NULL,
 `reward` int(8) NOT NULL,
 PRIMARY KEY (`order_product_id`),
 KEY `order_id` (`order_id`),
 KEY `product_id` (`product_id`)
) ENGINE=MyISAM AUTO_INCREMENT=1243823 DEFAULT CHARSET=utf8 COLLATE=utf8_bin

CREATE TABLE `product` (
 `product_id` int(11) NOT NULL AUTO_INCREMENT,
 `model` varchar(64) NOT NULL,
 `sku` varchar(64) NOT NULL,
 `upc` varchar(12) NOT NULL,
 `ean` varchar(14) NOT NULL,
 `jan` varchar(13) NOT NULL,
 `isbn` varchar(13) NOT NULL,
 `mpn` varchar(64) NOT NULL,
 `location` varchar(128) NOT NULL,
 `quantity` int(4) NOT NULL DEFAULT '0',
 `stock_status_id` int(11) NOT NULL,
 `image` varchar(255) DEFAULT NULL,
 `manufacturer_id` int(11) NOT NULL,
 `shipping` tinyint(1) NOT NULL DEFAULT '1',
 `price` decimal(15,4) NOT NULL DEFAULT '0.0000',
 `points` int(8) NOT NULL DEFAULT '0',
 `tax_class_id` int(11) NOT NULL,
 `date_available` date NOT NULL,
 `weight` decimal(15,8) NOT NULL DEFAULT '0.00000000',
 `weight_class_id` int(11) NOT NULL DEFAULT '0',
 `length` decimal(15,8) NOT NULL DEFAULT '0.00000000',
 `width` decimal(15,8) NOT NULL DEFAULT '0.00000000',
 `height` decimal(15,8) NOT NULL DEFAULT '0.00000000',
 `length_class_id` int(11) NOT NULL DEFAULT '0',
 `subtract` tinyint(1) NOT NULL DEFAULT '1',
 `minimum` int(11) NOT NULL DEFAULT '1',
 `sort_order` int(11) NOT NULL DEFAULT '0',
 `status` tinyint(1) NOT NULL DEFAULT '0',
 `date_added` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
 `date_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
 `viewed` int(5) NOT NULL DEFAULT '0',
 PRIMARY KEY (`product_id`),
 KEY `model` (`model`),
 KEY `stock_status_id` (`stock_status_id`),
 KEY `manufacturer_id` (`manufacturer_id`),
 KEY `tax_class_id` (`tax_class_id`),
 KEY `weight_class_id` (`weight_class_id`),
 KEY `length_class_id` (`length_class_id`)
) ENGINE=MyISAM AUTO_INCREMENT=135 DEFAULT CHARSET=utf8

CREATE TABLE `newsletter` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `email` varchar(254) NOT NULL,
 `agreed` tinyint(1) NOT NULL DEFAULT '0',
 PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8

这是SQL:

SELECT o.order_id,
       o.firstname,
       o.lastname,
       o.email,
       o.telephone,
       LOWER(l.code) AS language_code,
       o.currency_code,
       o.total,
       o.date_added,
       o.order_status_id,
       op.product_id,
       p.sku,
       op.price,
       op.model,
       op.name,
       op.tax,
       nl.agreed
FROM `order` o
JOIN LANGUAGE l ON l.language_id = o.language_id
LEFT JOIN order_product op ON op.order_id = o.order_id
LEFT JOIN product p ON p.product_id = op.product_id
LEFT JOIN newsletter nl ON nl.email = o.email
WHERE o.order_status_id IN(3,
                           5)
  AND o.order_id > '0'
ORDER BY o.order_id ASC
LIMIT 1

即使仅执行LIMIT 1,也无法弄清楚我们还能如何优化SQL。

我个人尝试避免加入varchars。 也就是说,如果您无法改善设计,则可以考虑在电子邮件列上添加索引,这至少会提高搜索性能。

希望能有所帮助

如果查询真的很长-我会尝试添加index(order_id,order_status_id)+可能将ORDER BY重写为

o.order_id,order_status_id的订单

在这种情况下,查询应“立即”完成。

如果仍然没有运气-您可以尝试先选择单个顺序,然后将其余表连接到该行。

(嗯,由于您使用的是myisam,请确保其他查询不会影响执行时间,例如,空闲服务器上的基准测试)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM