[英]MySQL query execution takes time with a single large table?
我制作了一個抓取腳本,將某些網站的信息下載到數據庫中,該數據庫用於進一步監控歷史列表信息及其總計數。
這是表的結構:
CREATE TABLE IF NOT EXISTS `biz_listing` (
`id` bigint(11) NOT NULL,
`lid` bigint(11) NOT NULL,
`cid` bigint(11) NOT NULL,
`name` varchar(300) NOT NULL,
`type` enum('homeservices','restaurants') NOT NULL,
`location` varchar(300) NOT NULL,
`businessID` varchar(300) NOT NULL,
`reviewcount` int(6) NOT NULL,
`rating` decimal(10,1) NOT NULL,
`city` varchar(300) NOT NULL,
`categories` varchar(300) NOT NULL,
`result_month` varchar(10) NOT NULL,
`updated_date` date NOT NULL,
KEY `businessID` (`businessID`),
KEY `updated_date` (`updated_date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
到目前為止,該腳本已經收集了大約350萬個結果,但是由於表中的大量記錄,腳本在查詢執行中花費了大量時間並導致超時問題。我們有一些查詢根據結果進行報告填充。抓取腳本是實時的並且正在填充結果,但是目前我無法根據聚合函數生成報告。
作為參考,這是用於聚合報告的查詢:
SELECT
COUNT(t.`type`) AS count,
COUNT(t.`businessID`) AS bizcount,
SUM(t.reviewcount) AS reviewcount,
t.`type`,t.`location` as city
FROM `biz_listing` t
INNER JOIN ( SELECT `businessID`,count(*) c
FROM `biz_listing`
where
DATE_FORMAT(`updated_date`, '%m %Y')
BETWEEN '01 2014' AND '02 2014'
group by `businessID` HAVING c = 2 ) t2 ON t2.`businessID` = t.`businessID`
where DATE_FORMAT(t.`updated_date`, '%m %Y')= '01 2014'
and t.type='homeservices'
GROUP BY t.location, t.result_month
上述查詢用於獲取商家列表計數及其審核計數的位置明智報告。 此處列表顯示2014年1月和2014年2月在數據庫中常見的企業匯總報告。
現在,來自表biz_listing的查詢執行花費了很多時間,並且通常該過程失敗。
說明
將所有數據存儲在一個表中的原因是什么? 當前腳本設置為繼續將信息抓取到同一個表本身。 我不能丟失任何數據,我也應該讓報告更快地進行查詢。
在某些論壇中,我發現表格大小在這種情況下不是問題,適當的分區會有所幫助。 由於我對數據感到擔心,我對制作實驗感到困惑和擔心。
由於表后面應該有更多的記錄,表的分區可以幫助我。 我只是從參考文檔中獲得了分區的想法,我對如何實現它感到困惑?
任何建議或建議都非常值得贊賞。如有必要,我還可以提供任何支持信息。
首先要做的是刪除DATE_FORMAT並檢查日期: -
SELECT
COUNT(t.`type`) AS count,
COUNT(t.`businessID`) AS bizcount,
SUM(t.reviewcount) AS reviewcount,
t.`type`,
t.`location` as city
FROM `biz_listing` t
INNER JOIN
(
SELECT `businessID`,count(*) c
FROM `biz_listing`
WHERE updated_date BETWEEN '2014/01/01' AND '2014/02/28'
GROUP BY `businessID`
HAVING c = 2
) t2 ON t2.`businessID` = t.`businessID`
WHERE updated_date BETWEEN '2014/01/01' AND '2014/02/28'
AND t.type='homeservices'
GROUP BY t.location, t.result_month
這方面的缺點是您必須指定該月的最后一天。 你可以使用LAST_DAY結束: -
SELECT
COUNT(t.`type`) AS count,
COUNT(t.`businessID`) AS bizcount,
SUM(t.reviewcount) AS reviewcount,
t.`type`,
t.`location` as city
FROM `biz_listing` t
INNER JOIN
(
SELECT `businessID`,count(*) c
FROM `biz_listing`
WHERE updated_date BETWEEN '2014/01/01' AND LAST_DAY('2014/02/01')
GROUP BY `businessID`
HAVING c = 2
) t2 ON t2.`businessID` = t.`businessID`
WHERE updated_date BETWEEN '2014/01/01' AND LAST_DAY('2014/02/01')
AND t.type='homeservices'
GROUP BY t.location, t.result_month
請注意,因為它在常量LAST_DAY上執行,所以在查詢中每次執行一次,而不是對它檢查的每一行執行一次。
您可能希望在表上添加覆蓋索引,並在表上添加update_date(即,一個索引具有兩個列)。 同樣,添加一個涵蓋businessID和update_date的索引。
編輯
再次查看您的查詢,看起來您正在尋找一個月的業務ID匹配,該記錄在該月和下個月有記錄。 如果我理解你想要的每個企業每個月只能有1條記錄(因此你計算它們超過2個月並使用HAVING ... = 2)。
如果這是正確的,那么你可以做多個連接,每個月一個: -
SELECT
COUNT(t0.type) AS count,
COUNT(t0.businessID) AS bizcount,
SUM(t0.reviewcount) AS reviewcount,
t0.type,
t0.location as city ,
t0.result_month
FROM biz_listing t0
INNER JOIN biz_listing t1
ON t0.businessID = t1.businessID
INNER JOIN biz_listing t2
ON t0.businessID = t2.businessID
WHERE t0.updated_date BETWEEN '2014/01/01' AND LAST_DAY('2014/01/01')
AND t1.updated_date BETWEEN '2014/01/01' AND LAST_DAY('2014/01/01')
AND t2.updated_date BETWEEN '2014/02/01' AND LAST_DAY('2014/02/01')
AND t0.type='homeservices'
GROUP BY t.location, t.type, t.result_month
請注意,如果我誤解了並且businessID每個月可以有多個記錄,那么這將無效。
請在updated_date
上創建數據庫表的索引並type
列,這將有助於快速執行查詢
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.