Question: In general it's necessary to delete about 110K rows from table `Nodes` but their id are not declared explicitly but are given from another table.

```
DECLARE @gh Table(id int);
INSERT INTO @gh (id) SELECT node_id FROM Relations;
DELETE FROM Nodes WHERE id NOT IN (SELECT DISTINCT id FROM @gh)

```

Selection (`SELECT DISTINCT id FROM @gh`) contains about 20K rows and server couldn't delete them due to expired timeout. What other ways to do it are there?

Answer: 
If you're keeping 20k of 130k, I'd do it a different way

```
SELECT N.* 
  INTO #NodesTemp 
FROM  
  Relations R JOIN Nodes N ON R.id = N.id;

TRUNCATE TABLE Nodes;

INSERT Nodes SELECT * FROM #NodesTemp;

DROP TABLE #NodesTemp;

```

Edit:

* do you have a DELETE trigger on Nodes?
* do you have foreign keys to Nodes that need checked?
Something like this might help. It will delete all Nodes where there is not a related Relation entry. The outer join should be much faster than using a "not in" clause with the sub query.

```
delete n
from Nodes n left outer join Relations r on n.id = r.node_id
where r.node_id is null

```