我使用MySQL和下面的背景:執行效率差異:一個SQL VS.兩個分裂SQL
mysql> show create table letter_index\G
*************************** 1. row ***************************
Table: letter_index
Create Table: CREATE TABLE `letter_index` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner` int(11) NOT NULL DEFAULT '0',
`target` int(11) NOT NULL DEFAULT '0',
`type` tinyint(4) unsigned NOT NULL DEFAULT '0',
`data_id` int(11) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `target_idx` (`target`,`type`)
) ENGINE=InnoDB
mysql> show create table letter_data\G
*************************** 1. row ***************************
Table: letter_data
Create Table: CREATE TABLE `letter_data` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`topic` varchar(255) DEFAULT NULL,
`message` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB
表letter_index
定義的字母關係:誰寫出來給誰接收,而表letter_data
存儲信件內容的消息。
表letter_index
第data_id
列參考表letter_data
主鍵id
。
我想得到某人的所有收到的消息。當我使用一個嵌套SQL來獲得結果時,它通常比兩個拆分SQL花費更多的時間。演示如下:
一個SQL:
mysql> select * from letter_data where id in (select data_id from letter_index where target=10718)
...
... # query result
...
78 rows in set (52.01 sec)
斯普利特:
mysql> select data_id from letter_index where target=10718;
...
... # query result
...
78 rows in set (0.25 sec)
mysql> select * from letter_data where id in (1,2,..`data_id result`..);
...
... # query result
...
78 rows in set (2.04 sec)
效率差異是巨大的!
解釋相對SQLS並有一些提示:
mysql> explain select * from letter_data where id in (select data_id from letter_index where target=10718);
+----+--------------------+--------------+------+---------------+------------+---------+-------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+--------------+------+---------------+------------+---------+-------+---------+-------------+
| 1 | PRIMARY | letter_data | ALL | NULL | NULL | NULL | NULL | 1103585 | Using where |
| 2 | DEPENDENT SUBQUERY | letter_index | ref | target_idx | target_idx | 4 | const | 78 | Using where |
+----+--------------------+--------------+------+---------------+------------+---------+-------+---------+-------------+
mysql> explain select data_id from letter_index where target=10718;
+----+-------------+--------------+------+---------------+------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+------+---------------+------------+---------+-------+------+-------+
| 1 | SIMPLE | letter_index | ref | target_idx | target_idx | 4 | const | 78 | |
+----+-------------+--------------+------+---------------+------------+---------+-------+------+-------+
mysql> explain select * from letter_data where id in (1,2,..`data_id result`..);
+----+-------------+-------------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | letter_data | range | PRIMARY | PRIMARY | 4 | NULL | 78 | Using where |
+----+-------------+-------------+-------+---------------+---------+---------+------+------+-------------+
我的問題是,爲什麼嵌套SQL表letter_data
possible_keys是NULL
,而個人一個是PRIMARY
?
謝謝你的時間!
爲什麼sql-server標記? – jarlh
@jarlh對不起, – hedleyyan
爲什麼不使用簡單的'INNER JOIN'?子查詢完全沒有意義,尤其是使用'IN'運算符。 – Mjh