Luc, 2) for unknown reasons RowCount-first is faster Thank you very much. You are genious. I tried this in my applicaton and this eliminates RowCount delay. Now there is only 3 sec delay which is caused by reading first two pages to cache like in MSDN sample. There is also SELECT COUNT(*) FROM mytable command but this seems not to cause any delay. the DGV seems to create objects for all the cells right from the start, and creating 108 million objects is bound to take a couple 108 millions of objects should take visible in Task Manager amout of memory. Task Manager memory (working set) does not show significat memory consumption. So I think that 108 million of objects are not created. Maybe this is related to sililar issue which posted here and in MS product feedback and which does not have any solution: Steps to reproduce: 1. Run code below 2. Double click in grid header in separation line between columns 1 ja 2 Observed: CPU usage goes to 100% for a long time. using System; using System.Windows.Forms; using System.Collections.Generic; class test { [STAThreadAttribute()] public static void Main() { Application.Run(new VirtualModeForm()); } } class VirtualModeForm : Form { private List<DataObject> m_Data = new List<DataObject>(); private List<bool> m_Visited = new List<bool>(); DataGridView m_Grid = new DataGridView(); public VirtualModeForm() { Controls.Add(m_Grid); m_Grid.CellValueNeeded += OnCellValueNeeded; InitData(); InitGrid(); } private void InitData() { for (int i = 0; i < 1000001 + 1; i++) { m_Visited.Add(false); DataObject obj = new DataObject(); obj.Id = i; obj.Val = 2 * i; m_Data.Add(obj); } } private void InitGrid() { m_Grid.Dock = DockStyle.Fill; m_Grid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCellsExceptHeader); m_Grid.VirtualMode = true; m_Grid.ReadOnly = true; m_Grid.ColumnCount = 3; m_Grid.Rows.Add(); m_Grid.Rows.AddCopies(0, 1000000); } private void OnCellValueNeeded(object sender, DataGridViewCellValueEventArgs e) { m_Visited[e.RowIndex] = true; if (e.ColumnIndex == 0) { e.Value = m_Data[e.RowIndex].Id; } else if (e.ColumnIndex == 1) { e.Value = m_Data[e.RowIndex].Val; } else if (e.ColumnIndex == 2) { Random rand = new Random(); e.Value = rand.Next(); } } } public class DataObject { private int m_Id; private int m_Val; public int Val { get { return m_Val; } set { m_Val = value; } } public int Id { get { return m_