[英]MySQL query optimization: how can I speed up this query?
這是我的桌子:
CREATE TABLE `tab_adasf` (
`adasf_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`adasf_shopId` int(10) unsigned NOT NULL,
`adasf_localId` bigint(20) unsigned NOT NULL,
`adasf_shopState` varchar(255) DEFAULT NULL,
`adasf_shopCity` varchar(255) DEFAULT NULL,
`adasf_shopName` varchar(255) DEFAULT NULL,
`adasf_shopDoor` varchar(255) DEFAULT NULL,
`adasf_computerName` varchar(255) DEFAULT NULL,
`adasf_channel` bigint(20) NOT NULL,
`adasf_totalInside` bigint(20) NOT NULL,
`adasf_totalOutside` bigint(20) NOT NULL,
`adasf_createdAt` datetime NOT NULL,
PRIMARY KEY (`adasf_id`),
KEY `adasf_shopId` (`adasf_shopId`),
KEY `adasf_localId` (`adasf_localId`),
KEY `adasf_shopState` (`adasf_shopState`,`adasf_shopCity`,`adasf_shopName`,`adasf_shopDoor`),
KEY `adasf_computerName` (`adasf_computerName`,`adasf_channel`,`adasf_createdAt`),
CONSTRAINT `tab_adasf_ibfk_1` FOREIGN KEY (`adasf_shopId`) REFERENCES `tab_shop` (`shop_id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1453500 DEFAULT CHARSET=utf8
如AUTO_INCREMENT的值所述:它具有1453500行。
為了生成XML文件,我需要如下結果集:
SELECT
UPPER(adasf_shopState) AS adasf_shopState,
UPPER(adasf_shopCity) AS adasf_shopCity,
UPPER(adasf_shopName) AS adasf_shopName,
UPPER(adasf_shopDoor) AS adasf_shopDoor,
adasf_computerName,
adasf_channel,
SUM(adasf_totalInside) AS adasf_totalInside,
SUM(adasf_totalOutside) AS adasf_totalOutside,
YEAR(adasf_createdAt) AS year,
MONTH(adasf_createdAt) AS month,
DAY(adasf_createdAt) AS day,
HOUR(adasf_createdAt) AS hour
FROM tab_adasf
WHERE 1=1 AND adasf_shopId = '1' AND HOUR(adasf_createdAt) BETWEEN '10:00' AND '21:00'
GROUP BY
UPPER(adasf_shopState),
UPPER(adasf_shopCity),
UPPER(adasf_shopName),
UPPER(adasf_shopDoor),
adasf_computerName,
adasf_channel,
YEAR(adasf_createdAt),
MONTH(adasf_createdAt),
DAY(adasf_createdAt),
HOUR(adasf_createdAt)
ORDER BY
UPPER(adasf_shopState),
UPPER(adasf_shopCity),
UPPER(adasf_shopName),
UPPER(adasf_shopDoor),
UPPER(adasf_computerName),
adasf_channel,
adasf_createdAt
運行和獲取需要3分鍾。
我的問題是:我在做什么錯? 如何加快此查詢或表的速度?
提前致謝!
為了加快查詢速度,您可以在tab_adasf(adasf_shopId)
上創建索引。 如果您有很多商店,這應該對性能有很大幫助。
如果您需要進行大量此類查詢,請考慮將adasf_createdAt
列拆分為日期部分和時間部分。 然后,您可以在tab_adasf(adasf_shopId, adasf_createdAt_time)
上創建索引tab_adasf(adasf_shopId, adasf_createdAt_time)
進一步幫助查詢。
通常,除非您有充分的理由,否則不建議將時間與日期時間分開。 這類查詢的性能提高構成了“充分的理由”。
正如其他人所說,這種查詢整個表的報表本質上是耗時的。 話雖如此,這是一個或兩個建議。
首先,消除GROUP BY
子句中的UPPER()
函數調用。 無論如何,MySQL的排序規則都不區分大小寫。
其次,嘗試在GROUP BY中使用此表達式,而不是GROUP BY
年,月,日,小時。
DATE_FORMAT(adasf_createdAt, '%Y-%m-%d %H:00:00')
這基本上會將您的createdAt
值四舍五入到前一個小時。
第三,讓我們重構讀取的WHERE
項目
HOUR(adasf_createdAt) BETWEEN '10:00' AND '21:00'
應該說
HOUR(adasf_createdAt) BETWEEN 10 AND 21
而且,如果您從主查詢中刪除該記錄,則會加快速度。 然后,您可以將查詢包裝在另一個查詢中,如下所示:
SELECT *
FROM ( /*your whole query without the WHERE HOUR() BETWEEN clause */
) AS q
WHERE q.hour BETWEEN 10 AND 21
最后,嘗試在
adasf_shopId, adasf_shopState, adasf_shopCity, adasf_shopName, adasf_shopDoor,
adasf_computerName, adasf_channel, adasf_CreatedAt,
adasf_totalInside, adasf_totalOutside
該索引具有滿足您的查詢所需的所有信息,這些信息按順序排列。 這可能會加快您的查詢速度。
因此,您的最終查詢如下所示:
SELECT *
FROM (
SELECT
UPPER(adasf_shopState) AS adasf_shopState,
UPPER(adasf_shopCity) AS adasf_shopCity,
UPPER(adasf_shopName) AS adasf_shopName,
UPPER(adasf_shopDoor) AS adasf_shopDoor,
adasf_computerName,
adasf_channel,
SUM(adasf_totalInside) AS adasf_totalInside,
SUM(adasf_totalOutside) AS adasf_totalOutside,
YEAR(adasf_createdAt) AS year,
MONTH(adasf_createdAt) AS month,
DAY(adasf_createdAt) AS day,
HOUR(adasf_createdAt) AS hour
FROM tab_adasf
WHERE 1=1
AND adasf_shopId = '1'
GROUP BY
adasf_shopState,
adasf_shopCity,
adasf_shopName,
adasf_shopDoor,
adasf_computerName,
adasf_channel,
DATE_FORMAT(adasf_createdAt, '%Y-%m-%d %H:00:00')
ORDER BY
adasf_shopState,
adasf_shopCity,
adasf_shopName,
adasf_shopDoor,
adasf_computerName,
adasf_channel,
DATE_FORMAT(adasf_createdAt, '%Y-%m-%d %H:00:00')
) AS q
WHERE q.hour BETWEEN 10 AND 21
對查詢的這種簡化加上覆蓋索引可能會使查詢更快。
請注意,我尚未調試此查詢,也沒有調試數據。
編輯:這個答案在MySQL中不起作用。
您必須使用全表掃描來檢查每一行,以查看它是否與HOUR(adasf_createdAt) BETWEEN '10:00' AND '21:00'
相匹配。
在HOUR(adasf_createdAt)
上創建功能索引。
另外,有關如何有效使用索引的出色教程,請參見http://use-the-index-luke.com 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.