我有一个 MySQL 5.1 InnoDB 表(customers
),其结构如下:
int record_id (PRIMARY KEY)
int user_id (ALLOW NULL)
varchar[11] postcode (ALLOW NULL)
varchar[30] region (ALLOW NULL)
..
..
..
表中大约有 700 万行。目前,正在查询该表:
SELECT * FROM customers WHERE user_id IN (32343, 45676, 12345, 98765, 66010, ...
在实际查询中,目前有超过560个user_id
在IN
子句中。表中有几百万条记录,此查询很慢!
表上有二级索引,第一个是 user_id
本身,我认为这会有所帮助。
我知道 SELECT(*)
是一件坏事,这将扩展到所需字段的完整列表。但是,上面没有列出的字段更多的是int
和double
。还有另外 50 人被退回,但报告需要他们。
我想有更好的方法来访问 user_id
的数据,但我想不出该怎么做。我最初的 react 是删除 user_id
字段上的 ALLOW NULL
,据我所知,NULL
处理会减慢查询速度?
如果您能指出比使用 IN ( )
方法更有效的方向,我将不胜感激。
编辑 Ran EXPLAIN,它说:
select_type = SIMPLE
table = customers
type = range
possible_keys = userid_idx
key = userid_idx
key_len = 5
ref = (NULL)
rows = 637640
Extra = Using where
这有帮助吗?
最佳答案
首先,检查 USER_ID
上是否有索引并确保它已被使用。
您可以通过运行 EXPLAIN
来完成。
其次,创建一个临时表并在 JOIN
中使用它:
CREATE TABLE temptable (user_id INT NOT NULL)
SELECT *
FROM temptable t
JOIN customers c
ON c.user_id = t.user_id
第三,您的查询返回多少行?
如果它返回几乎所有行,那么它只会很慢,因为它必须在连接 channel 上传输所有这些数百万行,一开始。
NULL
不会减慢您的查询速度,因为 IN
条件仅满足索引的非 NULL
值。
更新:
使用了索引,计划很好,只是它返回了超过 50 万行。
您真的需要将所有这些 638,000
行都放入报告中吗?
希望它没有被打印出来:对热带雨林、全局变暖等不利。
严肃地说,您的查询似乎需要聚合或分页。
关于sql - 在 MySQL 中使用集合的更快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/907323/