我正在尝试优化需要很长时间才能处理的 MySQL 查询。假设我们有两个表,一个用户表和一个购买表。两个表中都有约 20,000 行。
mysql>
SELECT NOW(),u.id
FROM users u
LEFT JOIN purchases p
ON p.user_id = u.id
WHERE
p.website_id = 1234
ORDER BY u.total_paid DESC
LIMIT 10;
+---------------------+-------+
| NOW() | id |
+---------------------+-------+
*snip*
+---------------------+-------+
10 rows in set (0.06 sec)
不是超级快但非常活泼。如果我除了改变之外什么都不改变u.id
,u.*
它会显着减慢:
mysql>
SELECT NOW(),u.*
FROM users u
LEFT JOIN purchases p
ON p.user_id = u.id
WHERE
p.website_id = 1234
ORDER BY u.total_paid DESC
LIMIT 10;
+---------------------+-------+
*snip*
+---------------------+-------+
10 rows in set (0.37 sec)
在您说“好吧,您永远不应该使用select *
”之前,请考虑您添加的字段越多,它会慢慢爬到那个时间长度,即命名一半要选择的字段将导致查询在 ~0.20 秒内执行,并且没有字段users 表大于 a varchar(255)
。
但是,如果我从我相对活泼的查询中获取 id,我只是:
mysql>
SELECT *
FROM users
WHERE id IN (*snip*);
+---------------------+-------+
*snip*
+---------------------+-------+
10 rows in set (0.01 sec)
所以我的两个查询:select u.id
plusselect u.* where id in
比我假设的类似查询要快。有没有搞错?
更多信息:用户表上有大约 30 个字段。同样,没有字段大于varchar(255)
更多更多信息:这两个查询的解释是:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: p
type: ref
possible_keys: PRIMARY,user_id_index,website_id_index,website_user_id_index,website_created_index,website_type_created_index,website_type_index,purchase_user_id_type_index,user_id_website_id_index,website_id_user_id_index
key: website_id_user_id_index
key_len: 9
ref: const
rows: 9976
Extra: Using where; Using index; Using temporary; Using filesort
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: u
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 8
ref: database.p.user_id
rows: 1
Extra:
编辑可能是因为它使用临时/文件排序,它必须从用户中选择 *,不知道哪些行最终会出现在最终结果集中?因此,这似乎是微不足道的额外数据量,但实际上这是选择表中的一大块之间的区别?如果这是正确的,有什么建议吗?