Reduce a huge low-rank matrix

You do not really need to delete rows and columns. Simply convert to Sparse matrix. Sparse matrix supports eigenvalue as is.

Since your matrix is full of zeros any way, this will be more efficient as well.

m0 = {{3, 7, 9}, {4, 8, 1}, {2, 6, 3}};
m = Table[0, {10}, {10}];
m[[4 ;; 6, 4 ;; 6]] = m0;
MatrixForm[m]

Mathematica graphics

convert to sparse and find eigenvalues

msp = SparseArray[m];
N@Eigenvalues[msp]

Mathematica graphics

It is the same eigenvalues as the dense matrix ofcourse

N@Eigenvalues[m]

Mathematica graphics

You can also take advantage of this method:

For many large sparse systems that occur in practical computations the Arnoldi algorithm is able to converge quite quickly.

 Eigenvalues[N@msp, 3, Method -> Arnoldi]

Mathematica graphics

LinearAlgebraMatrixComputations.html

WorkWithSparseMatrices.html


I might have found a way which is superior to the approach of deleting the rows and columns. It works as follows: You construct from the ArrayRules a new matrix, simply by re-numbering the matrix entries.

The implementation is straight forward

transformRules[m_] := 
 Module[{idX, idY, r = ArrayRules[m]},
  idX = DeleteDuplicates@Cases[r, ({x_Integer, _} -> _) :> x];
  idY = DeleteDuplicates@Cases[r, ({_, y_Integer} -> _) :> y];
  {idX, idY} = Thread[# -> Range[Length[#]]] & /@ {idX, idY};
  SparseArray[r /. ({x_, y_} -> n_) :> ({x /. idX, y /. idY} -> n)]
  ]

Details

Let's use a small example

m = ArrayPad[Partition[Range[9], 3], 2];
ArrayRules[m]

(* {{3, 3} -> 1, {3, 4} -> 2, {3, 5} -> 3, {4, 3} -> 
  4, {4, 4} -> 5, {4, 5} -> 6, {5, 3} -> 7, {5, 4} -> 8, {5, 5} -> 
  9, {_, _} -> 0} *)

What you see are the indexes for the non-zero elements. When we look only at the x-positions, we find that we have entries in

{3,3,3,4,4,4,5,5,5}

which means that there are only 3 distinct columns having non-zero entries: {3,4,5}. Now it doesn't matter where exactly those columns are, so we will simply rename them to {1,2,3} which puts them at the very beginning of our matrix (no matter how big the matrix is). Note that missing columns would simply be erased by this. So when we had elements at {4,23,45}, the result after renaming would still be {1,2,3}.

The two lines in the algorithm starting with idX = .. and idY = .. create exactly this list of duplicate-free, original column and row numbers. The next line starting with {idX,idY} = .. computes the renaming to id's starting with 1. After that we take the original array-rules and replace the old positions with our new ones and then we create a SparseArray from them.

Taking the initial m we get the following new rules:

transformRules[m] // ArrayRules

(* {{1, 1} -> 1, {1, 2} -> 2, {1, 3} -> 3, {2, 1} -> 
  4, {2, 2} -> 5, {2, 3} -> 6, {3, 1} -> 7, {3, 2} -> 8, {3, 3} -> 
  9, {_, _} -> 0} *)

The computation of Eigenvalues is invariant under this transformation and since the computation of ArrayRules is so incredible fast, the whole algorithm is fast, because it basically replaces only a few positions in a matrix of some probably some million entries.

Example

Using a big example:

m = ArrayPad[Partition[Range[9], 3], 5000];
m[[1, 1]] = -3;
m[[45, 23]] = 18;

we can now test this:

Eigenvalues[transformRules[m]]

(* {18, 3/2 (5 + Sqrt[33]), -3, 3/2 (5 - Sqrt[33]), 0} *)

This takes only 0.2 seconds here. If we compare this to the already made suggestions, we see:

Using Nassers method, you see that N@Eigenvalues[m] takes forever. Only the last line, where you restrict the number of Eigenvalues and use N inside is faster. It takes about 1.1 seconds here and has the disadvantages which comes from numeric, rather than exact calculations

Eigenvalues[N@m, 5, Method -> Arnoldi]

(* {16.1168, -3., -1.11684, 1.66277*10^-16 + 7.08214*10^-10 I,
   1.66277*10^-16 - 7.08214*10^-10 I} *)

The method suggested by Ray gives us exact Eigenvalues and needs about 1.23 seconds here

Eigenvalues[Nest[Transpose@DeleteCases[#, {0 ..}] &, m, 2]]

(* {18, 3/2 (5 + Sqrt[33]), -3, 3/2 (5 - Sqrt[33]), 0} *)

See Deleting entire row and/or column. The fastest solutions there are

Nest[Transpose@DeleteCases[#, {0 ..}]&, m, 2]     (* integers *)
Nest[Transpose@DeleteCases[#, {0. ..}]&, m, 2]    (* reals *)
Nest[Transpose@DeleteCases[#, {(0.|0)..}]&, m, 2] (* mixeds *)