【问题标题】:Very slow mysql query for reading orders (joins and group by)读取订单的mysql查询非常慢(加入和分组)
【发布时间】:2014-05-05 15:08:38
【问题描述】:

阅读订单的查询非常慢。我已经尝试了很多东西,但无法获得更快的查询。下面是查询和数据库表。当然,所有重要的字段都有索引。我注意到按函数删除分组会加快速度,但分组查询很重要。

有没有更好的方法来获得订单?提前致谢。

SELECT
orders.id AS orderId, orders.delivery_from, orders.delivery_to,
orders_products.product_id, orders_products.color_id, ,orders_products.size_id,
sum(orders_products.quantity) as quantity,
customers.id AS customerId, customers.name AS customerName,
products.name
FROM orders
    INNER JOIN orders_products ON orders_products.order_id=orders.id
    INNER JOIN customers ON customers.id=orders.customer_id
    INNER JOIN products ON orders_products.product_id=products.id
    LEFT JOIN orders_product_data ON orders_product_data.order_id=orders.id AND orders_product_data.product_id=orders_product.product_id AND orders_product_data.color_id=orders_product.color_id
WHERE orders.status='0' AND
(orders.delivery_from<='2014-05-05' AND orders.delivery_to>='2014-05-05') AND
((orders_products_data.delivery_from<='2014-05-05' || orders_products_data.delivery_to=0) AND (orders_products_data.delivery_from>='2014-05-05' || orders_products_data.delivery_to=0))
GROUP BY customer_id, product_id, color_id, size_id

客户

CREATE TABLE IF NOT EXISTS `customers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(90) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
);

产品

CREATE TABLE IF NOT EXISTS `products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
);

订单

CREATE TABLE IF NOT EXISTS `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `customer_id` int(11) NOT NULL,
  `delivery_from` date NOT NULL,
  `delivery_to` date NOT NULL,
  `status` int(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
);

订单产品

CREATE TABLE IF NOT EXISTS `orders_products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` int(11) NOT NULL DEFAULT '0',
  `product_id` int(11) NOT NULL DEFAULT '0',
  `color_id` int(11) NOT NULL DEFAULT '0',
  `size_id` int(11) NOT NULL DEFAULT '0',
  `quantity` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
);

颜色数据。下表存储了 order_id、product_id 和 color_id 组合的交货信息,因为不同颜色的产品的交货可能会发生变化。

CREATE TABLE IF NOT EXISTS `orders_products_data` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` int(11) NOT NULL DEFAULT '0',
  `product_id` int(11) NOT NULL DEFAULT '0',
  `color_id` int(11) NOT NULL DEFAULT '0',
  `delivery_from` date NOT NULL,
  `delivery_to` date NOT NULL,
  PRIMARY KEY (`id`)
);

解释查询

【问题讨论】:

  • 简单的经验法则:wherejoingrouporder 子句中使用的任何字段都应该有一个索引。现在看起来你唯一的索引是id 字段的主键。对整个查询执行explain ... 也会告诉您后台发生的情况。
  • 简单的经验法则:没有与单词 EXPLAIN 相关的相同查询的结果,这样的问题就没有任何意义。而只是盲目地添加索引会使事情变得更糟
  • 我已经对所有字段进行了索引,但没有将其发布在表格下方(我刚刚在问题中提到过)。
  • 应该是客户,已经翻译好了。
  • 现在 EXPLAIN 结果在哪里……?

标签: mysql database-performance


【解决方案1】:

你提到你有所有重要领域的索引。

仅用于您的信息 - 应根据访问路径而不是重要字段来准备索引。

在 '...' 和 '...' 之间替换 delivery_from 后检查订单、orders_product_data 并添加以下索引: 在订单上创建索引 idx_orders_status_delivery_from_to(status,delivery_from,delivery_to);

【讨论】:

  • 感谢您的回答。我为此做了一个额外的索引,现在它更快了。你有更多的索引技巧吗?如前所述,我已经为 order_id、product_id 和 color_id 字段的 orders_products_data 建立了索引。
  • 是否有可能在不使用与内部连接几乎相同的查询的情况下计算每个客户的产品数量?
  • @Stefan - 感谢您接受答案。以下链接将明确索引及其工作原理:stackoverflow.com/questions/1108/…programmerinterview.com/index.php/database-sql/what-is-an-index 我相信如果您了解索引的工作原理以及在表上添加索引后我们在 db 中获得的开销,您将能够找出所需的索引。
猜你喜欢
  • 1970-01-01
  • 2020-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-02
相关资源
最近更新 更多