To respond to (1) the speed question...
if you do indeed have 60K+ changes to process you don't need to execute 60K update statements. I would upload the 60K records to a temp table and invoke a stored procedure to do an UPDATE FROM...INNER JOIN statement between the real table and the temp table. Another possible idea if you don't want to rewrite what you've got is to filter out any rows in your datatable that have not been tainted. If there is no change then there is no reason to send those update statements...
Regarding (2) here is syntax...
this should work for you regarding sending NULL values as SqlParameters.
If mainDatatable.Rows(i)("rank") = DBNull.Value Then
q.Parameters.Add(New SqlParameter("@rankchange", SqlDbType.Int, 4) With { .Value = DBNull.Value })
Else
q.Parameters.Add(New SqlParameter("@rankchange", SqlDbType.Int, 4) With { .Value = mainDatatable.Rows(i)("rank") })
End If