mysql - 使用 4 个 JOINS 和优化 MySQL 查询

标签 mysql sql

我需要尽可能优化 MySQL 查询,因为当前数据库正在崩溃。我们有 5 张 table :

  • 订单 - 包含约 200 000 条记录
  • 语言 - 包含 2-5
  • 记录 order_product - 包含超过 200 000 条记录
  • 产品 - 包含少于 100 条记录
  • 新闻通讯 - 包含超过 50,000 条记录

当我们尝试加入电子邮件通讯表时,事情开始出错......

以下是每个的创建表:

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

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

最佳答案

我个人尽量避免在 varchar 上进行连接。也就是说,如果您无法改进设计,您可以考虑在电子邮件列上添加索引,这至少会提高搜索性能。

希望有帮助

关于mysql - 使用 4 个 JOINS 和优化 MySQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42834706/

相关文章:

mysql - 在创建表输出中显示排序规则

sql - 删除除每个 id 之外的行

sql - 与 SQL Server 中的临时表相比,为什么 CTE(通用表表达式)在某些情况下会减慢查询速度

php - Laravel 5 保存到数据库并返回 id

PROCEDURE 声明中无法识别 MySQL 标签语句

mysql - Oracle ADF - 在创建父实体时创建子实体

mysql - 从 mySQL 5.5 到 SQL Server 2005 的语法更改

mysql - 使用数据库和表对 MySQL 进行 Dockerize

php - Mysql查询$row返回 "bool(true)"而不是结果数组

sql - 具有多个值的通配符?