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: 
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

```
You don't need the `DINSTINCT` for this. It adds unnecessary overhead to the delete statement.

Second, why are you using a temporary table? Have you tried to combine these 2 statements into one?:

```
DELETE 
FROM Nodes 
WHERE id NOT IN 
      (SELECT node_id FROM Relations)

```

or delete the rows in smaller chunks, like @Serguei suggested:

```
SELECT 1

WHILE @@ROWCOUNT > 0
BEGIN
    DELETE TOP (1000)
    FROM Nodes 
    WHERE id NOT IN 
          (SELECT node_id FROM Relations)
END

```