выполняется запрос
OleDbCommand cmd=new OleDbCommand("select ...");
OleDbDataReader reader=cmd.ExecuteReader();
while(reader.Read()){
...
}
при выполнении Read() инфа берется из ОЗУ или каждый раз читается из базы?
Метод Read может считывать данные как из промежуточного буфера в памяти, так и напрямую из файла. Конкретные детали определяются используемой СУБД. Так как OLE DB чаще всего используют для работы с MS Access, имеет смысл рассмотреть именно его.
Для отслеживания обращений к файлу можно использовать механизм Event Tracing for Windows: Kernel tracing provider предоставляет событие FileIo_ReadWrite. Для использования ETW в C# подключим библиотеку Microsoft.Diagnostics.Tracing.TraceEvent. Напишем такой код для считывания 10 строк из БД и логирования событий чтения из файла (так как ETW выдает события с задержкой около секунды, между отдельными этапами работы с БД добавлены паузы, чтобы можно было отличить, какие события к чему относятся):
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Threading;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Session;
using System.Data.OleDb;
namespace ConsoleApp1
{
class Program
{
struct Timestamp : IComparable
{
public Timestamp(long t, string s)
{
tvalue = t;
descr = s;
}
public long tvalue { get; set; }
public string descr { get; set; }
public int CompareTo(object obj)
{
return (int)(this.tvalue - ((Timestamp)obj).tvalue );
}
public override string ToString()
{
return tvalue.ToString()+": "+descr;
}
}
static string filename = "C:\\Test\\Database1.mdb";
static TraceEventSession m_EtwSession;
static Stopwatch sw;
static List<Timestamp> timestamps = new List<Timestamp>(100000);
static object sync = new object();
static ManualResetEvent mre = new ManualResetEvent(false);
static void AddTimestamp(long t, string s)
{
lock (sync)
{
timestamps.Add(new Timestamp( t,s) );
}
}
static void AddTimestamp( string s)
{
lock (sync)
{
timestamps.Add(new Timestamp(sw.ElapsedMilliseconds, s));
}
}
static void ThreadProc()
{
int pid = Process.GetCurrentProcess().Id;
//Создаем сессию ETW и подписываемся на события чтения файлов
using (m_EtwSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName))
{
m_EtwSession.StopOnDispose = true;
m_EtwSession.EnableKernelProvider(KernelTraceEventParser.Keywords.FileIOInit |
KernelTraceEventParser.Keywords.DiskFileIO);
m_EtwSession.Source.Kernel.FileIORead += data =>
{
//сохраняем все события чтения файла БД текущим процессом
if (data.ProcessID == pid && data.FileName.ToLower().Trim() == filename.ToLower())
{
AddTimestamp((long)data.TimeStampRelativeMSec,
"Bytes read: " + data.IoSize.ToString());
}
};
lock (sync)
{
sw = new Stopwatch();
sw.Start();
}
//сигнализируем основному потоку о готовности
mre.Set();
//запускаем Event Tracing
m_EtwSession.Source.Process();
}
}
public static void Main(string[] argv)
{
//создаем поток для Event Tracing
Thread th = new Thread(ThreadProc);
th.IsBackground = true;
th.Start();
//ждем готовности второго потока
mre.WaitOne();
string constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+ filename+"; ";
string sql = "SELECT * FROM Table1";
//подключаемся к БД
OleDbConnection conn = new OleDbConnection(constr);
AddTimestamp( "Start");
Console.Write("Connecting...\r");
conn.Open();
AddTimestamp( "Connection.Open");
Thread.Sleep(1000);
//выполняем запрос и читаем первые 10 строк
using (conn)
{
OleDbCommand cmd = new OleDbCommand(sql, conn);
Console.Write("Executing SQL...\r");
OleDbDataReader reader = cmd.ExecuteReader();
AddTimestamp( "OleDbCommand.ExecuteReader");
Thread.Sleep(1000);
int i = 0;
int n = 10;
using (reader)
while (reader.Read())
{
AddTimestamp( "OleDbDataReader.Read ");
string s = reader[0].ToString();
Console.Write("Reading data... "+
s.PadLeft(5)+" ("+
i.ToString().PadLeft(4)+"/"+n.ToString()+") rows\r");
i++;
if (i > n) break;
Thread.Sleep(1000);
}
}
AddTimestamp( "End");
//завершаем сессию ETW
m_EtwSession.Dispose();
//выводим результаты
Console.Clear();
lock (sync)
{
timestamps.Sort();
foreach (var ts in timestamps)
{
Console.WriteLine(ts.ToString());
}
}
Console.WriteLine("Press any key to exit ...");
Console.ReadKey();
}
}
}
Результат выглядит так:
7: Start
34: Connection.Open
154: Bytes read: 65536
154: Bytes read: 4096
154: Bytes read: 4096
154: Bytes read: 4096
1037: OleDbCommand.ExecuteReader
1170: Bytes read: 4096
1170: Bytes read: 4096
1170: Bytes read: 4096
1170: Bytes read: 4096
2038: OleDbDataReader.Read
2172: Bytes read: 4096
3040: OleDbDataReader.Read
4041: OleDbDataReader.Read
5042: OleDbDataReader.Read
5153: Bytes read: 512
5175: Bytes read: 4096
5175: Bytes read: 4096
6042: OleDbDataReader.Read
7043: OleDbDataReader.Read
8044: OleDbDataReader.Read
9044: OleDbDataReader.Read
10045: OleDbDataReader.Read
10153: Bytes read: 512
11045: OleDbDataReader.Read
12081: End
По результатам видно, что Jet считывает данные блоками по 4096 байт (размер страницы в Access) и помещает в промежуточный буфер в памяти. Если требуемая строка находится в буфере, она берется из него, в противном случае осуществляется чтение следующего блока. События считывания по 512 байт являются, по видимому, периодическим опросом какой-то служебной информации (возможно, состояния блокировки записей), так как они наблюдаются постоянно, пока открыто соединение с БД (даже если ничего не считывать).
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Сколько раз в этом цикле будет выполняться строка j = j - 1; Почему цикл выполниться 50 раз? Обьясните, пожалуйста
Создать приложение «Дождь», которое позволяет отображать на экране падающие капли дождяКапля представляет собой набор графических элементов...
Вот мой код, который упаковывает файлы из папки в архив:
Я формирую FormData из файлов и передаю в контроллер, но мне так же нужно передавать туда текст из TextAreaВот мой код на JS :