Stewart,
I didn't check your long message, just seeing the few paragraph, wanted to add this as a side note:
One of the reasons an SQL insert/update would take a long time is that table's reccount is off by 1 in header compared to actual recordcount. This is not reported as an error when tablevalidate is set to 0 (or in earlier versions of VFP). TableValidate > 0 on the other hand causes to slow down if tables in question are not open and exclusive off.
Update SQL, unlike replace all, uses record locking and batch updates might be slower, fail while processing if another user is holding a lock on a record, set reprocess is auto and it might be waiting to acquire a lock (sort of deadlock) etc. Other users' opening the table type (un/buffered) and locks affect it in other words.
Besides the update itself check 'from ...' parts of it. That part might be slow due to several factors like not optimizable expressions, multiple UDF calls, not using == but =, cpcurrent() <> cpdbf() etc
Cetin Basoz