我在这里遇到的问题非常缓慢。部分问题可能是子查询中的tableA与其他表相比具有相当大的大小。
表格结构
*-------------------*------------------*-------------------*
| ID_TABLE | DATA_TABLE | DATA_TABLE_EXT |
*-------------------*------------------*-------------------*
| id n<|>1 id 1<|>n owner_id |
| foreign_id | owner_id | information |
| foreign_id_source | date_field | ... |
| ... | ... | |
*-------------------*------------------*-------------------*
QUERY
SELECT ID_TABLE.foreign_id_source, count(ID_TABLE.id) as count
FROM DATA_TABLE
LEFT JOIN ID_TABLE ON DATA_TABLE.id = ID_TABLE.id
WHERE DATA_TABLE.owner_id = 'some_id'
AND DATA_TABLE.date_field > 'some_date'
AND DATA_TABLE.id IN (
SELECT DATA_TABLE_EXT.owner_id FROM DATA_TABLE_EXT
JOIN DATA_TABLE ON DATA_TABLE_EXT.owner_id = DATA_TABLE.id
WHERE DATA_TABLE.owner_id = 'some_id'
GROUP BY DATA_TABLE.id
HAVING SUM(ABS(DATA_TABLE_EXT.information)) <> 0
)
GROUP BY ID_TABLE.foreign_id_source
ORDER BY count ASC
必修结果
*-------------------*-------------*
| foreign_id_source | count |
*-------------------*-------------*
| source1 | 45 |
| source2 | 10 |
| ... | |
*-------------------*-------------*
DATA_TABLE中的每个ID在ID_TABLE中可能有多个记录。 DATA_TABLE中的许多记录可能具有相同的owner_id。
我正在寻找带有foreign_id_source的data_table中的记录数,该记录按foreign_id_source分组,其中记录位于'some_date'之后,并且它的DATA_TABLE_EXT记录在信息字段中的值都不是0。
如果没有创建索引或其他数据库操作,是否有办法在性能方面改进此查询?
欢迎任何其他建议。
答案 0 :(得分:0)
经常将子查询移动到FROM
会有所帮助:
SELECT ID_TABLE.foreign_id_source, count(DATA_TABLE.id) as count
FROM ID_TABLE LEFT JOIN
DATA_TABLE
ON DATA_TABLE.id = ID_TABLE.id JOIN
(SELECT DATA_TABLE.id
FROM DATA_TABLE_EXT JOIN
DATA_TABLE
ON DATA_TABLE_EXT.owner_id = DATA_TABLE.id
WHERE DATA_TABLE.owner_id = 'some_value'
GROUP BY DATA_TABLE.id
HAVING SUM(ABS(DATA_TABLE_EXT.information)) <> 0
) xx
ON DATA_TABLE.id = xx.id
WHERE DATA_TABLE.owner_id = 'some_value' AND
DATA_TABLE.date_field > 'some_date'
GROUP BY x.field1
ORDER BY count ASC;
然后,您可以考虑索引。这些是tableX(field2, fieldZ, field1, fieldX)
,tableI(field1)
,tableX(field2,field1,fieldB), and
tableA(field1)`。
答案 1 :(得分:0)
重点是:SUM(ABS(DATA_TABLE_EXT.information)) <> 0
只有在至少一个 DATA_TABLE_EXT.information
非零时才能为真。所以我们不必sum()
他们,我们只需要检查是否存在非零值。
[我不知道mysql是否足够智能来处理exists()
,但理论上它更便宜,而且可以更快]
SELECT it.foreign_id_source, count(it.id) as count
FROM DATA_TABLE dt
LEFT JOIN ID_TABLE it ON dt.id = it.id
WHERE dt.owner_id = 'some_id'
AND dt.date_field > 'some_date'
AND EXISTS (
SELECT *
FROM DATA_TABLE_EXT x
JOIN DATA_TABLE dt2 ON x.owner_id = dt2.id
WHERE x.id =dt.id
AND dt2.owner_id = 'some_id'
AND x.information <> 0
)
GROUP BY it.foreign_id_source
ORDER BY count ASC
;