为什么这个查询运行得如此之慢?

时间:2011-08-03 07:58:12

标签: mysql sql query-optimization collation

我有两个MySQL表说A和B. A只包含一个varchar列(让我们称之为一个A1)有大约23000条记录。表B(70000条记录)有一些列,其中一列与表A中的A1相对应(让我们称之为B1)。我想知道A中哪些值不在B的相应列中,所以我使用:

SELECT A1
FROM A
LEFT JOIN B
    ON A1 = B1
WHERE B1 IS NULL 

A1和B1列都有定义的索引。这个查询仍然很慢。我运行解释,这是输出:

id  select_type table   type    possible_keys   key     key_len ref rows    Extra
1   SIMPLE      A       index   \N              PRIMARY 767     \N  23269   Using index
1   SIMPLE      B       ALL     \N              \N      \N      \N  70041   Using where; Not exists

更新:两个表的SHOW CREATE TABLE(更改了原始名称);

CREATE TABLE `A` (
  `A1` varchar(255) NOT NULL,
  PRIMARY KEY  (`A1`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8


CREATE TABLE `B` (
  `col1` int(10) unsigned NOT NULL auto_increment,
  `col2` datetime NOT NULL,
  `col3` datetime default NULL,
  `col4` datetime NOT NULL,
  `col5` varchar(30) NOT NULL,
  `col6` int(10) default NULL,
  `col7` int(11) default NULL,
  `col8` varchar(20) NOT NULL,
  `B1` varchar(255) default NULL,
  `col10` tinyint(1) NOT NULL,
  `col11` varchar(255) default NULL,
  PRIMARY KEY  (`col1`),
  KEY `NewIndex1` (`B1`)
) ENGINE=MyISAM AUTO_INCREMENT=70764 DEFAULT CHARSET=latin1
来自data_length

'nother edit:index_lengthSHOW TABLE STATUS

table   data_length index_length
A       465380      435200
B       5177996     1344512

5 个答案:

答案 0 :(得分:2)

您在OUTER JOIN中比较的两列的字符集不同。我不确定这是否是原因所以我测试并得到了这些结果:

SELECT A1
FROM A
LEFT JOIN B ON A1 = B1
WHERE B1 IS NULL

-- Table A..: 23258 rows, collation = utf8_general_ci
-- Table B..: 70041 rows, collation = latin1_swedish_ci
-- Time ....: I CANCELLED THE QUERY AFTER 20 MINUTES

-- Table A..: 23258 rows, collation = latin1_swedish_ci
-- Table B..: 70041 rows, collation = latin1_swedish_ci
-- Time ....: 0.187 sec

-- Table A..: 23258 rows, collation = utf8_general_ci
-- Table B..: 70041 rows, collation = utf8_general_ci
-- Time ....: 0.344 sec

解决方案:使两个表(或至少两列)的字符集相同。

答案 1 :(得分:1)

此查询将扫描表A的所有行,但如果您在B1上有索引,那么很可能它不会扫描表B:

select A1
from A
where not exists (
    select *
    from B
    where B.B1 = A.A1
)

在运行此查询或原始查询之前,您可以尝试运行ANALYZE TABLE以更新这些表的密钥分发信息:

ANALYZE TABLE A, B

如果这没有用,那么您可以尝试使用索引,例如:

select A1
from A ignore index (PRIMARY)
where not exists (
    select *
    from B force index (NewIndex1)
    where B.B1 = A.A1
)

答案 2 :(得分:0)

似乎 A1 B1 是大型游艇。

  

您为 A1 B1

创建了索引

确保将它们编入索引!

SELECT A1
FROM A
WHERE A1 NOT IN (
    SELECT B1 AS A1 From B;
)

答案 3 :(得分:0)

尝试此查询:

SELECT B1
FROM B
WHERE not B1  in (
  select A1
  from a
)

答案 4 :(得分:0)

如果我使用您的CREATE TABLES语句并在SELECT语句上运行EXPLAIN,我会得到以下结果:

id  select_type  table  type  possible_keys  key       key_len  ref  rows  Extra  
1   SIMPLE       A      index NULL           PRIMARY   767      NULL 2     Using index 
1   SIMPLE       B      index NULL           NewIndex1 258      NULL 4     Using where; Using index 

在我的MySQL版本(5.1.41)上,索引按预期使用,所以我认为这可能是MySQL中已经修复的错误,假设您的索引设置类似于发布的create table语句。您使用的是什么MySQL版本?