提高这个慢查询的性能

Posted

技术标签:

【中文标题】提高这个慢查询的性能【英文标题】:improve the performance of this slow query 【发布时间】:2015-07-23 09:34:27 【问题描述】:

我想调整这个查询以获得更好的性能。

查询:

SELECT `DeviceRawUsage`.`duration`, `DeviceRawUsage`.`current` 
FROM `epowerg`.`device_raw_usages` AS `DeviceRawUsage`   
WHERE `DeviceRawUsage`.`device_id` = 1 AND 
`DeviceRawUsage`.`outlet_id` = 1 AND 
`DeviceRawUsage`.`duration` >= '2015-06-01 00:00:00' AND 
`DeviceRawUsage`.`duration` <= '2015-06-30 23:59:59';

【问题讨论】:

可能值得将LIMIT 添加到您想要返回的结果数量中 - 如果适用于这种情况。 IE。如果您想要 10 个结果:在查询末尾添加 LIMIT 10 @user3065931 我无法限制它。我希望尽可能多地调整查询。还有其他方法可以使这个查询高效吗? 您是否为您的列 device_idoutlet_id 等定义了索引? 请告诉我们SHOW CREATE TABLE device_raw_usages的输出 提供表定义、mysql 设置和最重要的EXPLAIN 的输出。 @user3065931 - LIMIT 在这里没有影响,它永远不会使选择更快 - 请阅读 LIMIT 如何在内部工作(MySQL 收集所有记录,然后丢弃从 OFFSET 开始的所有记录以获取 LIMIT 行数)。 【参考方案1】:
CREATE TABLE `device_raw_usages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`device_id` int(11) DEFAULT NULL,
`outlet_id` int(11) NOT NULL,
`duration` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`current` float(11,4) DEFAULT NULL,
`voltage` float(11,4) NOT NULL,
`kw_used` float NOT NULL,
`outlet_total_kwh` float(11,4) DEFAULT NULL,
`outlet_kwh_demand_15` float(11,4) DEFAULT NULL,
`outlet_kw_demand_peak` float(11,4) DEFAULT NULL,
`submeter_real_kw` float(11,4) DEFAULT NULL,
`submeter_total_kwh` float(11,4) DEFAULT NULL,
`submeter_kwh_demand_15` float(11,4) DEFAULT NULL,
`submeter_kw_demand_peak` float(11,4) DEFAULT NULL,
`peak_voltage` float(11,2) DEFAULT NULL,
`peak_current` float(11,2) DEFAULT NULL,
`demand` float(11,2) DEFAULT NULL,
`inst_demand` float(11,2) DEFAULT NULL,
`hist_peek_demand` float(11,2) DEFAULT NULL,
`power_factor` float(11,2) DEFAULT NULL,
`crest_factor` float(11,2) DEFAULT NULL,
`frequency` varchar(20) DEFAULT NULL,
`app_power` float(11,2) DEFAULT NULL,
`tot_app_energy` float(11,2) DEFAULT NULL,
`tot_har_dist_vol` float(11,2) DEFAULT NULL,
`tot_har_dist_curr` float(11,2) DEFAULT NULL,
`har_x_dist_v` float(11,2) DEFAULT NULL,
`har_y_dist_v` float(11,2) DEFAULT NULL,
`har_z_dist_v` float(11,2) DEFAULT NULL,
`har_x_dist_c` float(11,2) DEFAULT NULL,
`har_y_dist_c` float(11,2) DEFAULT NULL,
`har_z_dist_c` float(11,2) DEFAULT NULL,
`interval` int(11) NOT NULL,
 PRIMARY KEY (`id`)
)  ENGINE=InnoDB AUTO_INCREMENT=1136511 DEFAULT CHARSET=latin1 |

【讨论】:

【参考方案2】:

要优化,添加一个复合索引:

INDEX(device_id, outlet_id, duration)

不相关的 cmets:

FLOAT(m,n) 几乎总是做错事。考虑DECIMAL(m,n) 或普通FLOAT

这些列真的是最优的吗?在适当的地方使用NOT NULL

编辑

假设您已经建立了表,您可以通过以下方式添加索引:

ALTER TABLE device_raw_usages ADD INDEX(device_id, outlet_id, duration);

此特定索引对您提供的一个 SELECT 有益。它可能对其他SELECTs 有帮助,也可能没有帮助。 Here 是一本关于如何为给定的SELECT 编写“最佳”INDEX 的简短食谱。

【讨论】:

你能在查询中使用索引并发布它吗?我是新手。我想知道你是怎么做的..我会暗示我的其他问题。

以上是关于提高这个慢查询的性能的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的解决方案这么慢,如何提高查询的性能?

mysql查询性能问题,加了order by速度慢了

后端接口如何提高性能?从MySQLESHBASE等技术一起探讨下!

lucene3.0 通过IndexSearcher.doc(i)获取Document 非常慢,如何提高性能?

后端接口如何提高性能?

JOIN 慢查询