INNER JOIN或STRAIGHT_JOIN

时间:2015-08-24 11:16:27

标签: mysql sql

我有两张桌子:

  

| users_transactions |       CREATE TABLE users_transactions(         user_id int(11)NOT NULL,         transaction_id int(11)NOT NULL,         独特的钥匙user_id_transaction_id_uniqueuser_idtransaction_id)       )ENGINE = InnoDB DEFAULT CHARSET = utf8 |

     

|交易|         CREATE TABLE transactions(         id int(11)NOT NULL AUTO_INCREMENT,         name varchar(45)DEFAULT NULL,         transaction_date datetime DEFAULT NULL,         PRIMARY KEY(id),         KEY index_transactions_on_transaction_datetransaction_date)       )ENGINE = InnoDB AUTO_INCREMENT = 2000000 DEFAULT CHARSET = utf8

我尝试运行此SQL

SELECT `transactions`.`id`, `transactions`.`transaction_date` 
FROM `transactions` 
INNER JOIN `users_transactions` 
ON `transactions`.`id` = `users_transactions`.`transaction_id` 
WHERE `users_transactions`.`user_id` = 71720 
ORDER BY `transactions`.`transaction_date` DESC 
LIMIT 25 OFFSET 0;

用户71720有超过27000个交易,这个SQL将花费> 4S。我试着解释一下,它显示了

*************************** 1. row ***************************

id: 1   select_type: SIMPLE   
table: users_transactions   
type: ref possible_keys: user_id_transaction_id_unique    
key: user_id_transaction_id_unique   
key_len: 4  
ref: const    
rows: 52968  <--- It returns too many rows, bad smell 
Extra: Using index; Using temporary; Using file sort

*************************** 2. row ***************************

id: 1   select_type: SIMPLE   
table: transactions    
type: eq_ref possible_keys: PRIMARY    
key: PRIMARY   
key_len: 8    
ref: NULL   
rows: 1    
Extra: Using where 2 rows in set (0.00 sec)

表明它没有使用index_transactions_on_transaction_date

当我尝试使用STRAIGHT_JOIN时,它正在使用index_transactions_on_transaction_date,并在用户71720上快速执行。但对于没有多笔交易的其他用户,STRAIGHT_JOININNER JOIN慢得多。

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

这是您的查询:

SELECT t.id, t.transaction_date
FROM transactions t INNER JOIN
     users_transactions ut
     ON t.id = ut.transaction_id
WHERE ut.user_id = 71720
ORDER BY t.transaction_date DESC
LIMIT 25 OFFSET 0;

你遇到一个问题,你有两个不同的执行计划,一个最适合某些数据,一个最适合其他人。我不认为MySQL在处理这个问题上做得很好。

您有什么方法可以将transaction_date列放入user_transactions吗?这将使您能够针对这两种情况优化查询。

我建议将其重写为: