mysql - 有没有办法提高这个查询的性能?

标签 mysql sql performance

我有这样的模型:

Customer  (1) .... (n)  Orders

我可以通过如下简单查询找到一位客户的所有订单:

select * from Orders o join Customer c on o.customer_id = c.id;

我需要找到所有客户的所有当前(今天)订单(如果有),并呈现所有客户。

例如。我期待的结果是这样的:

Customer     OrderDate           OrderStatus
Customer 1   2/1/2015 12:00:00        active
Customer 2   2/1/2015 13:00:00        closed
Customer 3    null                    null
Customer 4    null                    null 

表格应该如下所示:

Customers
Customer 1
Customer 2
Customer 3
Customer 4

Orders        timestamp     CustomerID
Active   1/1/2015  15:00:00   1
Closed   1/1/2015  08:00:00   1
Canceled 1/1/2015  09:00:00   1
Closed   2/1/2015  11:00:00   1
Active   2/1/2015  12:00:00   1  //This is the last one of "TODAY" C1
Active   3/1/2015  18:00:00   1 
Closed   2/1/2015  13:00:00   2  //This is the last one of "TODAY" C2

正在运行的查询是:

select o.status, o.date, c.name from (
     select c.*, (
          select o1.id from orders o1 
             where o1.id_customer = c.id and o1.date between '2/1/2015 00:00:00' and "2/1/2015 23:59:59" 
             order by o1.date desc limit 1) as o
     from cliente c
) c left join orders o on o.id = c.o;

问题在于,对于少量订单和客户,查询需要几秒钟的时间才能执行。我预计短期内订单数量将会增加,客户数量也会增加。

有没有办法提高这个查询的效率?我觉得我解决问题的方式是错误的。

旁注:我无法修改模型,也无法包含新列。我的第一个解决方案是包含给客户的最后一个订单,并在每次创建订单时进行设置,但遗憾的是我无法更改数据库。

提前致以问候和感谢!

[编辑]

表定义

CREATE TABLE `customer` (
    `id` char(36) NOT NULL,
    `name` varchar(120) NOT NULL,
    `cabin` enum('CABIN_A','CABIN_B','CABIN_C','CABIN_D','CABIN_E') DEFAULT NULL,
    `addressId` char(36) NOT NULL,
    `phone` varchar(45) DEFAULT NULL,
    `datetime` timestamp NULL DEFAULT NULL,
    `number` bigint(20) unsigned NOT NULL,
    `unitId` char(36) DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `id_UNIQUE` (`id`),
    UNIQUE KEY `number_UNIQUE` (`number`),
    KEY `addressId_idx` (`addressId`),
    KEY `fk_customer_unit_idx` (`unitId`),
    CONSTRAINT `fk_customer_unit` FOREIGN KEY (`unitId`) REFERENCES `unidad` (`unitId`) ON DELETE NO ACTION ON UPDATE NO ACTION,
    CONSTRAINT `fk_address_customer` FOREIGN KEY (`addressId`) REFERENCES `address` (`addressId`) ON DELETE CASCADE ON UPDATE NO ACTION,
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `orders` (
    `id` char(36) NOT NULL,
    `customerId` char(36) NOT NULL,
    `status` enum('ACTIVE','CLOSED','CANCELED') NOT NULL,
    `datetime` timestamp NULL DEFAULT NULL,
    `comment` varchar(700) DEFAULT NULL,
    `programDate` timestamp NULL DEFAULT NULL,
    `cabin` varchar(10) DEFAULT NULL,
    `unitId` char(36) DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `id_UNIQUE` (`id`),
    KEY `fk_orders_unit_idx` (`unitId`),
    CONSTRAINT `fk_customer_orders` FOREIGN KEY (`customerId`) REFERENCES `customer` (`customerId`) ON DELETE NO ACTION ON UPDATE NO ACTION,
    CONSTRAINT `fk_unit` FOREIGN KEY (`unitId`) REFERENCES `unit` (`unitId`) ON DELETE NO ACTION ON UPDATE NO ACTION,
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

最佳答案

一个没有子查询的简单LEFT JOIN应该可以加快速度:

select  o.status, o.date, c.name 
from Orders o 
join Customer c
    on o.customer_id = c.id
    AND o.orderDate = '2/1/2015'

我假设,根据最初的问题(来自“我期待的结果...”),您希望为今天没有订单的任何客户返回 NULL。

我有点困惑为什么客户 #1 的 2 个“已关闭”订单和 1 个“已取消”订单不属于“我期望的结果”的一部分,因为您不需要 orderStats = 'Active' 在您的“正在运行的查询”中...显然,由于您列出了客户 #2 的已关闭订单,因此实际上并不要求订单处于打开状态 - 也许您想详细说明这一点。

关于mysql - 有没有办法提高这个查询的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29250125/

相关文章:

SQL - 使用 sum() 检索获得值的第一行

MySQL 查询在排序时使用文件排序,尽管有索引

sql - 通过 Oracle SQL 检索范围内的数字

java - 开启JIT日志,分析汇编代码,对代码优化有帮助吗?

android - `Cursor` 包含查询的所有行还是仅包含第一行?

php - mysql查询,自定义顺序

mysql - mysql 中存储过程的并行性?

java - 使您的应用程序随服务器更新的最佳方式是什么?

mysql - 结合 LIKE 和 AND 的 SQL 给出了错误的结果

php - 按供应商分组获取多行的多个总和