0

我有一个有效的查询,但它需要永远。它基本上返回数据库 D 中的表 T(具有连接条件)中的所有行,而不是数据库 D2 中的表 T2(也具有连接条件)中的所有行:

select f.* from D.frames f
join D.items i on i.id=f.item_id
where f.item_id not in (
    select f2.item_id
    from D2.frames f2
    join D2.items i2 on i2.id=f2.item_id
    where i2.primary_type='xxx'
)

非常感谢您对加快此查询的任何帮助。

4

2 回答 2

1

您的问题之一可能是跨数据库NOT IN未作为常量集执行。

尝试SELECT从 D2 进入临时表(因此您有一个固定的内存集),然后将该临时表用于NOT IN子句。

更好LEFT JOIN的是,您可以输入临时表并在字段中检查 a NULL

以下未经测试:

CREATE TEMPORARY TABLE TempTable (item_id int); 
INSERT INTO 
    TempTable 
FROM 
    D2.frames f2
JOIN 
    D2.items i2 ON i2.id=f2.item_id
WHERE 
    i2.primary_type='xxx'; 

SELECT 
    f.* 
FROM 
    D.frames f
JOIN 
    D.items i ON i.id=f.item_id
LEFT OUTER JOIN
    TempTable t ON t.item_id = f.item_id
WHERE
    t.item_id IS NULL
于 2013-05-07T22:44:36.823 回答
1

据我所知,当您使用where aField in (select...)子查询时,会对表中的每一行进行一次评估,因此这确实是性能上的一大损失。

我建议你使用left join

select 
    f.*
from 
    (D.frames as f
    inner join D.items as i on f.item_id = i.id)
    left join (
        select f2.item_id
        from D2.frames as f2
        inner join D2.items as i2 on f2.item_id = i2.id
        where i2.primary_type='xxx'
    ) as a on f.item_id = a.item_id
where a.item_id is null;

作为替代方案,请考虑创建一个临时表并将其分为两步:

-- Step 1. Create the temporary table with the ids you need
drop table if exist temp_myTable;
create temporary table temp_myTable
    select f2.item_id
    from D2.frames as f2
    inner join D2.items as i2 on f2.item_id = i2.id
    where i2.primary_type='xxx';
-- Step 2. Add the appropriate indexes
alter temporary table temp_myTable
    add primary key (item_id); -- Or add index idx_item_id(item_id)
-- Step 3. Run your query using the newly created temp table
select 
    f.*
from 
    (D.frames as f
    inner join D.items as i on f.item_id = i.id)
    left join temp_myTable as a on f.item_id = a.item_id
where a.item_id is null;

希望这可以帮助

于 2013-05-07T22:47:16.900 回答