為什麼此查詢的 Group by 和 Have 子句非常慢?
我有這個查詢,當對 100K 行執行時,需要永遠導致我的系統具有 2 GB Ram 和標準 MySQL 安裝。
現在在我的數據庫中,我有兩個表,chitentry 和 chitentrygroup。兩者都包含超過 100K 行。當我執行以下查詢時,結果始終處於掛起狀態,我沒有得到任何輸出並且查詢繼續執行。
SELECT SQL_CALC_FOUND_ROWS chitentrygroupid, chitentrygroupdate, chitentryno, chitbookno, chitamount, entryamount, entryweight, employeename, accountname, rate, monthentry FROM (SELECT chitentrygroup.chitentrygroupid, chitentrygroup.chitentrygroupdate, chitentry.chitentryno, chitentry.chitbookno, Round(( chitentry.chitamount ), 0) AS chitamount, chitentry.entryamount, chitentry.entryweight, employee.employeename, account.accountname, chitentry.rate, chitentry.monthentry FROM chitentrygroup LEFT OUTER JOIN chitentry ON chitentry.chitentrygroupid = chitentrygroup.chitentrygroupid LEFT OUTER JOIN employee ON employee.employeeid = chitentrygroup.employeeid LEFT OUTER JOIN account ON account.accountid = chitentrygroup.accountid WHERE chitentrygroup.status NOT IN ( 0, 3, 8 ) AND chitentrygroup.industryid IN ( 3 ) AND 1 = 1 AND 1 = 1 AND 1 = 1 GROUP BY 1 HAVING 1 = 1 ORDER BY chitentrygroup.chitentrygroupid DESC ) AS t LIMIT 0, 10
現在,當我刪除 SQL_CALC_FOUND_ROWS 時, Group By 並擁有查詢的一部分。查詢速度很快。我所說的上述任何內容的存在都會使查詢卡在這個大表上。
我應該如何使用 Group By、Having 和 SQL_CALC_FOUND_ROWS 子句優化此查詢?
去掉外層:
SELECT SQL_CALC_FOUND_ROWS ... FROM (SELECT ... ORDER BY chitentrygroup.chitentrygroupid DESC ) AS t LIMIT 0, 10
–>
SELECT SQL_CALC_FOUND_ROWS ... ORDER BY chitentrygroup.chitentrygroupid DESC LIMIT 0, 10
這也將修復您可能沒有註意到的錯誤。派生表返回一組無序的行。也就是說,允許優化器忽略您擁有的
ORDER BY
公式中的 。這給你的不是前 10 行,而是一些任意的 10 行。
FOUND_ROWS
過去了。您是否注意到搜尋引擎首先移動到“大約 1,000,000 次點擊”,然後擺脫了計數?你真的需要計數嗎?你有什麼索引
chitentrygroup
?特別是,這可能是有益的:INDEX(industryid, status)
你在使用 InnoDB 嗎?的價值是多少
innodb_buffer_pool_size
。對於 2GB 的小型機器(或 VM),它應該不超過 400M。您正在執行什麼版本的 MySQL?舊版本預設為 8M 或 128M。這些太小。
什麼是映射?有一個
employee
嗎chitentrygroupid
?那是“1:許多”。account
和怎麼樣chitentry
?如果這些都是 1:many,你就不需要GROUP BY
——這才是真正的反派。也就是說,如果您可以
SELECT
使用 chitentrygroupids,通過ORDER BY
並且LIMIT
不需要,ORDER BY
您可以避免使用JOIN + GROUP BY
.
可能它的語法是錯誤的:
和 1 = 1 和 1 = 1 和 1 = 1 按 1 分組
交換
group by 1 #第一列的名稱
嘗試交易
按 table.field 排序
例子
此方法耗時稍長 SQL_CALC_FOUND_ROWS;您是否嘗試過使用 count()
我發現使用某些方法來獲得響應時間很酷
http://phpdevblog.niknovo.com/2009/06/mysql-pagination-sql-calc-found-rows-vs-count-query.html