简体   繁体   English

我的查询未使用索引,如何使用解释计划并使用MySQL修复此缓慢的查询

[英]My query is not using my indexes, how do i use explain plan and fix this slow query with MySQL

I have this query that is running slow (16 seconds), it only has 44085 records in the biggest table. 我的查询运行缓慢(16秒),最大表中只有44085条记录。 Any suggestions or anything that sticks out? 有什么建议或建议吗?

thanks for any help 谢谢你的帮助

SELECT  u.`vid`,  u.`userID`,  u.`localConID`,  u.`lastran`,  u.`laststatus`,  
        u.`lastmessage`,  u.`active`
        ,u.`autorundaily`,  u.`autorunmonthly`,  u.`fileslocation`
         ,c.`conid`, c.`fname`, c.`lname`, c.`homephone`, c.`cellphone` , c.`email` , 
        DATE_FORMAT(u.`lastran`,'%d/%m/%y %k:%i') lastranFormatted, u.`retrys`
FROM virtual_alerts_users u
LEFT JOIN virtual_alerts_cons c ON c.referid = u.localConID
WHERE u.userID = 9581

When i do an explain i get:: 当我做一个解释我得到:

  id  |  select_type  |  table  |  type  |  possible_keys  |  key  |  key_len  |  ref  |  rows  |  extra
  1   |  SIMPLE       |  u      |  ALL   |  Index 3        | null  |  null     |  null |  459   |  Using where
  1   |  SIMPLE       |  c      |  ALL   |  null           | null  |  null     | null  |  44085 |

The tables look like:: 表格如下:

CREATE TABLE `virtual_alerts_users` (
`vid` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`userID` INT(11) NOT NULL DEFAULT '0',
`localConID` VARCHAR(10) NULL DEFAULT NULL,
`encrpytPW` VARCHAR(100) NULL DEFAULT NULL,
`lastran` TIMESTAMP NULL DEFAULT NULL,
`laststatus` INT(11) NULL DEFAULT NULL,
`lastmessage` TEXT NULL,
`active` TINYINT(4) NOT NULL DEFAULT '0',
`autorundaily` TINYINT(4) NOT NULL DEFAULT '0',
`autorunmonthly` TINYINT(4) NOT NULL DEFAULT '0',
`fileslocation` VARCHAR(512) NULL DEFAULT NULL,
`retrys` TINYINT(4) NULL DEFAULT '0',
PRIMARY KEY (`vid`),
UNIQUE INDEX `Index 2` (`localConID`),
INDEX `Index 3` (`userID`)
)

- -

CREATE TABLE `virtual_alerts_cons` (
`conid` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`userID` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`vid` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`fname` VARCHAR(50) NULL DEFAULT NULL,
`lname` VARCHAR(50) NULL DEFAULT NULL,
`referid` VARCHAR(10) NULL DEFAULT NULL,
`level` VARCHAR(2) NULL DEFAULT NULL,
`status` VARCHAR(2) NULL DEFAULT NULL,
`lang` VARCHAR(15) NULL DEFAULT NULL,
`homephone` VARCHAR(15) NULL DEFAULT NULL,
`cellphone` VARCHAR(15) NULL DEFAULT NULL,
`address` VARCHAR(255) NULL DEFAULT NULL,
`email` VARCHAR(255) NULL DEFAULT NULL,
`birthday_mon` TINYINT(4) NULL DEFAULT '0',
`birthday_day` TINYINT(4) NULL DEFAULT '0',
`anv_mon` TINYINT(4) NULL DEFAULT '0',
`anv_day` TINYINT(4) NULL DEFAULT '0',
`anv_cnt` TINYINT(4) NULL DEFAULT '0',
`lasthash` BIGINT(20) NULL DEFAULT '0',
`lastupdated` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`conid`),
UNIQUE INDEX `Index 3` (`userID`, `referid`),
INDEX `Index 2` (`userID`),
INDEX `Index 4` (`vid`)
) 

You have no index on referid in virtual_alerts_cons , but you do have a combined index on userID and referid . 您在virtual_alerts_cons没有对referid索引,但是在userIDreferid确实具有组合索引。

To force MySQL to use that, change your join condition to: 要强制MySQL使用它,请将连接条件更改为:

LEFT JOIN
    virtual_alerts_cons c
ON
    c.referid = u.localConID
        AND
    c.userId = u.userID

Alternatively, you could create an additional index on referid . 或者,您可以在referid上创建一个附加索引。

The table virtual_alerts_con doesn't have the right kind of index for referid. 表virtual_alerts_con没有正确的referenceid索引类型。

CREATE TABLE `virtual_alerts_cons` (
`conid` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`userID` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`vid` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`fname` VARCHAR(50) NULL DEFAULT NULL,
`lname` VARCHAR(50) NULL DEFAULT NULL,
`referid` VARCHAR(10) NULL DEFAULT NULL,
`level` VARCHAR(2) NULL DEFAULT NULL,
`status` VARCHAR(2) NULL DEFAULT NULL,
`lang` VARCHAR(15) NULL DEFAULT NULL,
`homephone` VARCHAR(15) NULL DEFAULT NULL,
`cellphone` VARCHAR(15) NULL DEFAULT NULL,
`address` VARCHAR(255) NULL DEFAULT NULL,
`email` VARCHAR(255) NULL DEFAULT NULL,
`birthday_mon` TINYINT(4) NULL DEFAULT '0',
`birthday_day` TINYINT(4) NULL DEFAULT '0',
`anv_mon` TINYINT(4) NULL DEFAULT '0',
`anv_day` TINYINT(4) NULL DEFAULT '0',
`anv_cnt` TINYINT(4) NULL DEFAULT '0',
`lasthash` BIGINT(20) NULL DEFAULT '0',
`lastupdated` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`conid`),
UNIQUE INDEX `Index 3` (`userID`, `referid`),
INDEX `Index 2` (`userID`),
INDEX `Index 5` (`referid`),
INDEX `Index 4` (`vid`)
) 

You can also probably change the query to something like this 您也可以将查询更改为这样的内容

SELECT  u.`vid`,  u.`userID`,  u.`localConID`,  u.`lastran`,  u.`laststatus`,  
        u.`lastmessage`,  u.`active`
        ,u.`autorundaily`,  u.`autorunmonthly`,  u.`fileslocation`
         ,c.`conid`, c.`fname`, c.`lname`, c.`homephone`, c.`cellphone` , c.`email` , 
        DATE_FORMAT(u.`lastran`,'%d/%m/%y %k:%i') lastranFormatted, u.`retrys`
FROM virtual_alerts_users u
LEFT JOIN virtual_alerts_cons c ON c.referid = u.localConID AND c.userId = 9581
WHERE u.userID = 9581

That will probably take advantage of the Index 3 with both userId and referid. 这可能会利用同时具有userId和Referid的索引3。

The explain plan shows you that it is scanning all the rows of the virtual_alerts_con table because it can't use any indexes. 解释计划向您显示它正在扫描virtual_alerts_con表的所有行,因为它不能使用任何索引。 Your "Index 3" isn't helping because its a multi-column index. 您的“索引3”无济于事,因为它是多列索引。 There are restrictions on how you use multi-column indexes. 使用多列索引的方式受到限制。

If you have an index with A, B, C, you can't search on just column C. You can search with just A, or A+B, or A+B+C. 如果索引包含A,B,C,则不能仅在列C上进行搜索。可以仅使用A或A + B或A + B + C进行搜索。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM