Is there any way to find the number of pages read by each operator in query plan?
Io statistics per table was added to actual execution plans starting in SQL Server 2016. It was ported to SQL Server 2014 SP2 as well.
I executed a simple query and uploaded the query plan here. Comparing the results of SET STATISTICS IO ON:

Table 'BIG_TABLE'. Scan count 1, logical reads 921659, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'SMALL_TABLE'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

To what's in the XML for the actual plan:
&lt;RunTimeInformation&gt;
  &lt;RunTimeCountersPerThread Thread=&quot;0&quot; ActualRows=&quot;6451600&quot; ActualRowsRead=&quot;6451600&quot; Batches=&quot;0&quot; ActualEndOfScans=&quot;1&quot; ActualExecutions=&quot;1&quot; ActualExecutionMode=&quot;Row&quot; ActualElapsedms=&quot;972&quot; ActualCPUms=&quot;972&quot; ActualScans=&quot;1&quot; ActualLogicalReads=&quot;921659&quot; ActualPhysicalReads=&quot;0&quot; ActualReadAheads=&quot;0&quot; ActualLobLogicalReads=&quot;0&quot; ActualLobPhysicalReads=&quot;0&quot; ActualLobReadAheads=&quot;0&quot; /&gt;
&lt;/RunTimeInformation&gt;
&lt;TableScan Ordered=&quot;false&quot; ForcedIndex=&quot;false&quot; ForceScan=&quot;false&quot; NoExpandHint=&quot;false&quot; Storage=&quot;RowStore&quot;&gt;
  &lt;DefinedValues /&gt;
  &lt;Object Database=&quot;[TEST]&quot; Schema=&quot;[dbo]&quot; Table=&quot;[BIG_TABLE]&quot; IndexKind=&quot;Heap&quot; Storage=&quot;RowStore&quot; /&gt;
&lt;/TableScan&gt;


&lt;RunTimeInformation&gt;
  &lt;RunTimeCountersPerThread Thread=&quot;0&quot; ActualRows=&quot;10&quot; ActualRowsRead=&quot;10&quot; Batches=&quot;0&quot; ActualEndOfScans=&quot;1&quot; ActualExecutions=&quot;1&quot; ActualExecutionMode=&quot;Row&quot; ActualElapsedms=&quot;0&quot; ActualCPUms=&quot;0&quot; ActualScans=&quot;1&quot; ActualLogicalReads=&quot;2&quot; ActualPhysicalReads=&quot;0&quot; ActualReadAheads=&quot;0&quot; ActualLobLogicalReads=&quot;0&quot; ActualLobPhysicalReads=&quot;0&quot; ActualLobReadAheads=&quot;0&quot; /&gt;
&lt;/RunTimeInformation&gt;
&lt;TableScan Ordered=&quot;false&quot; ForcedIndex=&quot;false&quot; ForceScan=&quot;false&quot; NoExpandHint=&quot;false&quot; Storage=&quot;RowStore&quot;&gt;
  &lt;DefinedValues /&gt;
  &lt;Object Database=&quot;[TEST]&quot; Schema=&quot;[dbo]&quot; Table=&quot;[SMALL_TABLE]&quot; IndexKind=&quot;Heap&quot; Storage=&quot;RowStore&quot; /&gt;
&lt;/TableScan&gt;

Reveals a perfect match in this case.