簡體   English   中英

MySQL-加快查詢速度,避免文件排序和臨時

[英]MySQL - speed up query avoid filesort and temporary

我的MySQL查詢速度很慢。 我有3個表:作業(200k條記錄),位置(300k),位置(700k)。

SELECT
    j.job_offerid
FROM `job_offer` AS j 
INNER JOIN `job_offer_localitymap` AS d ON d.`job_offerid` = j.`job_offerid` AND 
    `gps_localityid` IN(35, 3301, 3302, 3303, 3305, 3306, 3307, 3308, 124, 3811, 3805, 3709, 3808, 3809) 
WHERE 
    j.`status` = 1 AND 
    j.`job_offerid` IN(
        SELECT `job_offerid` 
        FROM `job_offer_positionmap` 
        WHERE `cb_job_positionid` IN (1001, 6, 629, 7, 8, 9, 10, 11, 12, 13, 1, 15, 16, 17))
ORDER BY j.`job_offerid` DESC 
LIMIT 3

我必須過濾位置和地點,因此我使用了IN。

說明:在哪里使用; 使用索引; 使用臨時; 使用文件排序; 臨時開始

僅使用行的表方案:

CREATE TABLE `job_offer` (
  `job_offerid` int(13) NOT NULL AUTO_INCREMENT,
  `status` int(13) NOT NULL DEFAULT '1',
  PRIMARY KEY (`job_offerid`),
  KEY `status` (`status`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `job_offer_localitymap` (
  `job_offer_localitymapid` int(13) NOT NULL AUTO_INCREMENT,
  `gps_localityid` int(13) NOT NULL,
  `job_offerid` int(13) NOT NULL,
  PRIMARY KEY (`job_offer_localitymapid`),
  KEY `gps_localityid` (`gps_localityid`),
  KEY `job_offerid` (`job_offerid`),
  KEY `gps_localityid_job_offerid` (`gps_localityid`,`job_offerid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;

CREATE TABLE `job_offer_positionmap` (
  `job_offer_positionmapid` int(13) NOT NULL AUTO_INCREMENT,
  `cb_job_positionid` int(13) NOT NULL,
  `job_offerid` int(13) NOT NULL,
  PRIMARY KEY (`job_offer_positionmapid`),
  KEY `cb_job_positionid` (`cb_job_positionid`),
  KEY `job_offerid` (`job_offerid`),
  KEY `cb_job_positionid_job_offerid` (`cb_job_positionid`,`job_offerid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;

索引無處不在。

謝謝你的任何建議

您的加入將受益於復合材料

job_offer_localitymap.(job_offerid,gps_localityid)

也就是說,與該表中的當前組合相反。

因此,您可以刪除以下兩個:

  KEY `gps_localityid` (`gps_localityid`),
  KEY `job_offerid` (`job_offerid`),

然后,您將剩下兩個復合索引,每個復合索引的最左端都由其他受益於上述兩個的查詢使用,我剛才說過刪除


在您的查詢行5中,保持一致並使用別名j因為我必須搜尋(不長)以查看哪個表


我認為job_offer中的KEY statusstatus )可能相對沒有用,但我不知道其他查詢。 但是,由於您的數據類型很薄,因此job_offer(job_offerid,status)上的復合物可能會使您的許多查詢飛起來,因為這將是一個covering index不需要在數據頁之后。


至於job_offer_positionmap ,這可能是一個job_offer_positionmap ,它刪除了慢的子查詢,並且開發人員也選擇在那里添加復合。 從概念上講,該連接類似於第一個連接。


我一般認為in子句沒有問題,因為mysql CBO基於成本的優化器應該處理該問題。


但這只是建議,因為添加索引並非毫無缺點。 這是一種脆弱的平衡行為,但最終您可能會發現此查詢不僅會飛行,還會查詢您的其他查詢。


您正在使用join進行過濾。 因此,我將該邏輯移至where子句:

SELECT j.job_offerid
FROM `job_offer` 
WHERE j.`status` = 1 AND 
      j.`job_offerid` IN (SELECT jop.`job_offerid` 
                          FROM `job_offer_positionmap` jop
                          WHERE `cb_job_positionid` IN (1001, 6, 629, 7, 8, 9, 10, 11, 12, 13, 1, 15, 16, 17)
                         ) AND
      j.`job_offerid` IN (SELECT jop.`job_offerid` 
                          FROM `job_offer_localitymap` jol
                          WHERE jol.gps_localityid IN (35, 3301, 3302, 3303, 3305, 3306, 3307, 3308, 124, 3811, 3805, 3709, 3808, 3809)
                         )                        
ORDER BY j.`job_offerid` DESC 
LIMIT 3;

然后,對於此查詢,您需要以下索引:

  • job_offer(狀態,job_offerid描述)
  • job_offer_positionmap(cb_job_positionid,job_offerid)
  • job_offer_localitymap(gps_localityid,job_offerid)

結果查詢應使用第一個索引進行過濾,並使用order by子句。 然后,它將使用其他兩個索引進行過濾。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM