MySQL 一些查询永远不会执行

MySQL some queries never exectue

我正在进行我的第一个数据科学项目,我在使用 MySQL Workbench 进行极其缓慢的查询时遇到了一些麻烦。

这是我的3个table(每个都来自各个网站的数据集,已经清理并插入MySQL):

CREATE TABLE IF NOT EXISTS `starbucks` (
   `STORE_NUMBER` varchar(20) NOT NULL,
   `CITY` varchar(50) NOT NULL,
   `STATE` char(2) NOT NULL,
   `ZIPCODE` char(5) NOT NULL,
   `LONG` varchar(10) NOT NULL,
   `LAT` varchar(10) NOT NULL,
   PRIMARY KEY (`STORE_NUMBER`)
   )ENGINE=InnoDB")

CREATE TABLE IF NOT EXISTS `income`(
   `STATEFIPS` char(2) NOT NULL,
   `STATE` char(2) NOT NULL,
   `ZIPCODE` char(5) NOT NULL,
   `AGI_STUB` tinyint NOT NULL,
   `NUM_RETURNS` float(15,4) NOT NULL,
   `TOTAL_INCOME` float(15,4) NOT NULL,
   PRIMARY KEY (`STATE`, `ZIPCODE`, `AGI_STUB`)
   )ENGINE=InnoDB")

CREATE TABLE IF NOT EXISTS `diversity`(
   `COUNTY` varchar(50) NOT NULL,
   `STATE` char(2) NOT NULL,
   `INDEX` float(7,6) NOT NULL,
   `1` float(3,1) NOT NULL,
   `2` float(3,1) NOT NULL,
   `3` float(3,1) NOT NULL,
   `4` float(3,1) NOT NULL,
   `5` float(3,1) NOT NULL,
   `6` float(3,1) NOT NULL,
   `7` float(3,1) NOT NULL,
   PRIMARY KEY (`COUNTY`, `STATE`)
   )ENGINE=InnoDB")

starbucks 有 13,608 条记录, income 有 166,740 条记录, diversity 有 3,143 条记录。

我正在尝试的查询 运行:

SELECT  i.TOTAL_INCOME,
    CASE
        WHEN s.STORE_NUMBER IS NOT NULL THEN 1
        ELSE 0
    END AS has_starbucks
  FROM  income as i
  LEFT  OUTER JOIN starbucks as s
    ON  i.ZIPCODE = s.ZIPCODE

如果我将结果限制为 1,000 行,它会 运行 很快,但是我需要获取所有记录(没有行限制),这会导致查询永远不会返回,并最终超时并断开我与 MySQL 服务器的连接。 过去,在为拥有数百万条记录的数据库工作时,我从来没有遇到过这么多麻烦。

我需要做什么 table 优化来解决这个问题?我需要更改哪些 MySQL 设置?欢迎任何其他建议。

编辑 查询的 'Duration' 似乎永远不会超过 0.500 秒,'Fetch' 部分持续 > 120 秒。我不确定这是否有用。

第一个问题是在连接列上创建适当的索引

 CREATE INDEX idx1 ON starbucks (ZIPCODE );
 CREATE INDEX idx2 ON income (ZIPCODE );

或添加您 select

列的冗长索引
CREATE INDEX idx2 ON income (ZIPCODE , TOTAL_INCOME);

并使用解释计划检查行为

这对解决性能问题没有太大作用,但会解决重复行问题 -

 SELECT  i.TOTAL_INCOME, 1 AS has_starbucks
 FROM  income as i
 WHERE i.Zipcode in (Select zipcode from Starbucks)
   UNION
 SELECT  i.TOTAL_INCOME, 0 AS has_starbucks
 FROM  income as i
 WHERE i.Zipcode not in (Select zipcode from Starbucks)

EXISTS 有时比 IN

更有效
 SELECT  i.TOTAL_INCOME, 1 AS has_starbucks
 FROM  income as i
 WHERE EXISTS 
 (   SELECT 1 
     FROM Starbucks s
     WHERE s.zipcode = i.Zipcode
 )
   UNION
 SELECT  i.TOTAL_INCOME, 0 AS has_starbucks
 FROM  income as i
 WHERE NOT EXISTS 
 (   SELECT 1 
     FROM Starbucks s
     WHERE s.zipcode = i.Zipcode
 )