我知道在没有数据库表的情况下可能很难优化这个查询,但我是一个新手,不会相信自己,需要花很多时间来原谅这个问题,比如 50 秒,我想不出另一种方法来做到这一点,只是看起来很长
欢迎提供任何提示以加快速度
SELECT SUM(x) AS d
FROM ( 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 = files.id
INNER JOIN filedata fm ON files.id = fm.id
INNER JOIN filetag v ON files.id = v.id
INNER JOIN filetype ft ON files.id = ft.id
LEFT JOIN definitiondata dd ON files.id = dd.id
WHERE ( ( NOT filename LIKE '%abc2%' AND filename LIKE '%abc%' )
OR ( filename LIKE '%abc2%' AND fm.dset = 1 ) )
AND v.type BETWEEN 0 and 4
AND v.length BETWEEN 3 and 7
AND v.decoder = 1
AND v.lighting = 'bright'
AND NOT vmd.time = 'xx:xx:Xx'
AND ft.country = 'IQ'
UNION
i have a bunch of them like 4 with different conditions and
stuff
最佳答案
我不明白你的问题,我不知道我是否理解错误,但是:
( 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 和键列为空。最重要的是,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 都能直接找到匹配的记录使用索引记录在所有其他表中,而不必扫描整个表。
关于mysql - 慢sql查询优化,,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18580594/