0

I've been reading similar questions to mine on SO and googling for days and can't seem to find a solution that works for my situation. Please see the details below. When I run the sql statement below, it takes over a minute. It also is not using the index on tableA.col4. Why?

Like I said, I have been googling for quite some time but seem to be running in circles at this point. Any help is greatly appreciated!

---THE DETAILS--- (Sorry it is soooo long, but better to have all the info, I guess)

I have the following two tables, table A and B:

tableA: (5M rows...will eventually be 20M)

tableA | CREATE TABLE `tableA` (
  `col1` varchar(50) NOT NULL,
  `col2` int(10) NOT NULL DEFAULT '0',
  `col3` varchar(300) DEFAULT NULL,
  `col4` varchar(50) DEFAULT NULL,
  `col5` datetime DEFAULT NULL,
  PRIMARY KEY (`col1`,`col2`),
  KEY `col4` (`col4`),
  KEY `col5` (`col5`),
  KEY `col1` (`col1`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |

Indexes on tableA:

+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table   | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tableA |          0 | PRIMARY    |            1 | col1         | A         |        NULL |     NULL | NULL   |      | BTREE      |         |               |
| tableA |          0 | PRIMARY    |            2 | col2         | A         |     4780162 |     NULL | NULL   |      | BTREE      |         |               |
| tableA |          1 | col4       |            1 | col4         | A         |         426 |     NULL | NULL   | YES  | BTREE      |         |               |
| tableA |          1 | col5       |            1 | col5         | A         |     2390081 |     NULL | NULL   | YES  | BTREE      |         |               |
| tableA |          1 | col1       |            1 | col1         | A         |     2390081 |     NULL | NULL   |      | BTREE      |         |               |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

tableB: (1M rows...will eventually be around 5M)

| tableB | CREATE TABLE `tableB` (
  `col1` varchar(300) NOT NULL DEFAULT '',
  `col2` varchar(300) DEFAULT NULL,
  `col3` int(10) DEFAULT NULL,
  `col4` varchar(300) DEFAULT NULL,
  `col5` varchar(300) DEFAULT NULL,
  `col6` varchar(300) DEFAULT NULL,
  `col7` varchar(300) DEFAULT '0',
  `col8` varchar(300) DEFAULT '0',
  `col9` varchar(300) DEFAULT '0',
  `col10` varchar(300) DEFAULT NULL,
  `col11` varchar(300) DEFAULT NULL,
  `col12` mediumtext,
  `col13` decimal(15,2) DEFAULT NULL,
  `col14` decimal(15,2) DEFAULT NULL,
  `col15` varchar(300) DEFAULT NULL,
  `col16` varchar(300) DEFAULT NULL,
  `col17` decimal(15,2) DEFAULT NULL,
  `col18` decimal(15,2) DEFAULT NULL,
  `col19` varchar(300) DEFAULT NULL,
  `col20` varchar(300) DEFAULT NULL,
  `col21` decimal(15,2) DEFAULT NULL,
  `col22` decimal(15,2) DEFAULT NULL,
  `col23` varchar(300) DEFAULT NULL,
  PRIMARY KEY (`col1`),
  KEY `col3` (`col3`),
  KEY `col5` (`col5`),
  KEY `col2` (`col2`),
  KEY `col1` (`col1`),
  FULLTEXT KEY `col12` (`col12`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |

Indexes on tableA:

+----------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table    | Non_unique | Key_name      | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tableB |          0 | PRIMARY        |            1 | col1           | A         |      989765 |     NULL | NULL   |      | BTREE      |         |               |
| tableB |          1 | col3           |            1 | col3           | A         |        9799 |     NULL | NULL   | YES  | BTREE      |         |               |
| tableB |          1 | col5           |            1 | col5           | A         |       98976 |     NULL | NULL   | YES  | BTREE      |         |               |
| tableB |          1 | col2           |            1 | col2           | A         |      197953 |     NULL | NULL   | YES  | BTREE      |         |               |
| tableB |          1 | col1           |            1 | col1           | A         |      989765 |     NULL | NULL   |      | BTREE      |         |               |
| tableB |          1 | col12          |            1 | col12          | NULL      |           1 |     NULL | NULL   | YES  | FULLTEXT   |         |               |
+----------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

EXPLAIN:

EXPLAIN SELECT *
FROM tableA LEFT OUTER JOIN tableB ON tableA.col1 = tableB.col1 
WHERE tableA.col4 NOT IN ('8/G','2','9/D','7','6/M') ORDER BY tableA.col5 DESC LIMIT 25

+----+-------------+----------+--------+-------------------+---------+---------+-----------------------+---------+-----------------------------+
| id | select_type | table    | type   | possible_keys     | key     | key_len | ref                   | rows    | Extra                       |
+----+-------------+----------+--------+-------------------+---------+---------+-----------------------+---------+-----------------------------+
|  1 | SIMPLE      | tableA   | ALL    | col4              | NULL    | NULL    | NULL                  | 4780162 | Using where; Using filesort |
|  1 | SIMPLE      | tableB   | eq_ref | PRIMARY, col1     | PRIMARY | 902     | mydb.tableA.col1      |       1 |                             |
+----+-------------+----------+--------+-------------------+---------+---------+-----------------------+---------+-----------------------------+

PROFILING:

Status  Time
starting    0.000012
Waiting for query cache lock    0.000003
checking query cache for query  0.000079
checking permissions    0.000004
checking permissions    0.000003
Opening tables  0.000013
System lock 0.000006
Waiting for query cache lock    0.000027
init    0.000028
optimizing  0.000008
statistics  0.000404
preparing   0.000009
executing   0.000003
Sorting result  2.135376
Sending data    0.004359
Waiting for query cache lock    0.000004
Sending data    0.004735
Waiting for query cache lock    0.000004
....
....
....   
Sending data    0.008573
Waiting for query cache lock    0.000006
Sending data    0.005630
Waiting for query cache lock    0.000005
Sending data    0.005760
Waiting for query cache lock    0.000005
Sending data    0.005295
Waiting for query cache lock    0.000005
Sending data    0.005239
Waiting for query cache lock    0.000004
Sending data    0.004954
Waiting for query cache lock    0.000004
Sending data    82.246597
end 0.000012
query end   0.000004
closing tables  0.000009
freeing items   0.000014
logging slow query  0.000002
logging slow query  0.000003
cleaning up 0.000003
4

2 に答える 2

2

また、tableA.col4のインデックスも使用していません。なんで?

ええと、tableA.col4 NOT IN( '8 / G'、 '2'、 '9 / D'、 '7'、 '6 / M')が原因です。MySQLは、NOTINを満たすためにインデックスを実際に使用することはできません。

何が起こっているのかというと、MySQLはtableAの約500万行すべてを実行し、tableA.col4がIN( '8 / G'、 '2'、 '9 / D'、 '7'、 ' 6 / M')。次に、そのセットをcol5で降順で並べ替え、(うまくいけば)その中から上位25行を選択して、結合を実行します。

MySQLはインデックスを逆の順序で処理し、tableA.col4 NOT INを満たす25行を取得すると停止すると思われるため、tableAのcol5とcol4の複数列インデックス(この順序で)がこのクエリに役立つ可能性があります。 (「8 / G」、「2」、「9 / D」、「7」、「6 / M」)。

したがって、私の提案は次のようになります。

CREATE INDEX ix_tableA_col5_col4 ON tableA(col5,col4);

次に、クエリを再実行します。

于 2012-11-24T23:11:35.723 に答える
1

Hmm. Just doing a quick shoot. The profiling output says that Sending data takes 82.246597, so maybe you get lots of output which takes lots of time to transfer?

于 2012-11-24T21:54:08.790 に答える