我对您的查询一无所知,我不知道我是否误解了,但是:
( SELECT COUNT(*) AS x
FROM ( SELECT DISTINCT id
FROM streamsignature
WHERE time < '2013-01-03'
AND signature = 'v'
AND signaturelevel = 'check'
) AS subq
INNER JOIN files ON subq.id
行数是文件表的 id 吗?就像你一样,在你的 join 子句上有
ON subq.id = files.id
唯一选择的字段是x,它是行数
反正...
我认为更像是索引问题。您真的应该使用 EXPLAIN 来找出缺少哪些索引。
例如:
EXPLAIN SELECT * FROM orderdetails d
INNER JOIN orders o ON d.orderNumber = o.orderNumber
INNER JOIN products p ON p.productCode = d.productCode
INNER JOIN productlines l ON p.productLine = l.productLine
INNER JOIN customers c on c.customerNumber = o.customerNumber
WHERE o.orderNumber = 10101G
执行该查询将产生:
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: l
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 7
Extra:
********************** 2. row **********************
id: 1
select_type: SIMPLE
table: p
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 110
Extra: Using where; Using join buffer
********************** 3. row **********************
id: 1
select_type: SIMPLE
table: c
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 122
Extra: Using join buffer
********************** 4. row **********************
id: 1
select_type: SIMPLE
table: o
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 326
Extra: Using where; Using join buffer
********************** 5. row **********************
id: 1
select_type: SIMPLE
table: d
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2996
Extra: Using where; Using join buffer
5 rows in set (0.00 sec)`
如果查看上面的结果,您可以看到错误查询的所有症状。但是即使我写了一个更好的查询,结果仍然是一样的,因为没有索引。连接类型显示为“ALL”(这是最差的),这意味着 MySQL 无法识别可以在连接中使用的任何键,因此 possible_keys 和 key 列为空。最重要的是,rows 列显示 MySQL 扫描每个表的所有记录以进行查询。这意味着执行查询时,它将扫描 7 × 110 × 122 × 326 × 2996 = 91,750,822,240 条记录以找到四个匹配的结果。这真的很可怕,而且它只会随着数据库的增长而呈指数级增长。
现在让我们添加一些明显的索引,例如每个表的主键,并再次执行查询。作为一般经验法则,您可以将查询的 JOIN 子句中使用的列视为键的良好候选者,因为 MySQL 将始终扫描这些列以查找匹配的记录。
ALTER TABLE customers
ADD PRIMARY KEY (customerNumber);
ALTER TABLE employees
ADD PRIMARY KEY (employeeNumber);
ALTER TABLE offices
ADD PRIMARY KEY (officeCode);
ALTER TABLE orderdetails
ADD PRIMARY KEY (orderNumber, productCode);
ALTER TABLE orders
ADD PRIMARY KEY (orderNumber),
ADD KEY (customerNumber);
ALTER TABLE payments
ADD PRIMARY KEY (customerNumber, checkNumber);
ALTER TABLE productlines
ADD PRIMARY KEY (productLine);
ALTER TABLE products
ADD PRIMARY KEY (productCode),
ADD KEY (buyPrice),
ADD KEY (productLine);
ALTER TABLE productvariants
ADD PRIMARY KEY (variantId),
ADD KEY (buyPrice),
ADD KEY (productCode);
添加索引后,让我们再次重新运行相同的查询,结果应如下所示:
********************** 1. row **********************
id: 1
select_type: SIMPLE
table: o
type: const
possible_keys: PRIMARY,customerNumber
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 2. row **********************
id: 1
select_type: SIMPLE
table: c
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
********************** 3. row **********************
id: 1
select_type: SIMPLE
table: d
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 4
Extra:
********************** 4. row **********************
id: 1
select_type: SIMPLE
table: p
type: eq_ref
possible_keys: PRIMARY,productLine
key: PRIMARY
key_len: 17
ref: classicmodels.d.productCode
rows: 1
Extra:
********************** 5. row **********************
id: 1
select_type: SIMPLE
table: l
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 52
ref: classicmodels.p.productLine
rows: 1
Extra:
5 rows in set (0.00 sec)
添加索引后,扫描的记录数减少到了 1 × 1 × 4 × 1 × 1 = 4。这意味着对于 orderdetails 表中每条 orderNumber 10101 的记录,MySQL 能够直接找到所有匹配的记录其他表使用索引,而不必求助于扫描整个表。