Проблемы с производительностью между SQL Server и C # - PullRequest
3 голосов
/ 17 января 2012

Я хочу проверить, является ли for этот цикл между DataTable более быстрым или выполнить эту операцию в SQL Server.Итак, я создаю таблицу следующим образом:

CREATE TABLE [dbo].[tbl_Test_Data](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[LName] [nvarchar](50) NOT NULL,
[f_date] [datetime] NOT NULL,
[flag] [bit] NOT NULL,
[Age] [int] NOT NULL,
[amount] [decimal](23, 5) NOT NULL,
   CONSTRAINT [PK_tbl_Test_Data] PRIMARY KEY CLUSTERED ([Id] ASC)

, а затем создаю индекс для столбца Age:

CREATE NONCLUSTERED INDEX [idx_age] ON [dbo].[tbl_Test_Data] 
(
[Age] ASC
)
INCLUDE ( [Id], [f_date]) 

и вставляю 100000 строк тестовых данных:

DECLARE @a   INT
SET @a = 100000;

WHILE @a >= 0 
BEGIN
DECLARE @d DATETIME ;
SET @d = DATEADD(d,CAST(RAND() * 100 AS INT),GETDATE());

DECLARE @b BIT;
IF @a % 2 =0
    SET @b=0;
ELSE
    SET @b=1;

    INSERT INTO tbl_Test_data
    VALUES(N'nima',
           N'agha',
           DATEADD(d,CAST(RAND() * 100 AS INT),GETDATE()),
           @b,
           CAST(RAND() * 100 AS INT),
           CAST(RAND()  AS DECIMAL(23,5)) )

SET @a=@a -1;
END

Затем я создаю C # windows-приложение с 2 кнопками.Для обновления из SQL-запроса я пишу этот код:

private void button2_Click(object sender, EventArgs e)
{
   Stopwatch sq = new Stopwatch();
   sq.Start();

   using (SqlConnection cn = new SqlConnection("Data Source=.;Initial Catalog=Northwind;Integrated Security=True"))
   {
       using (SqlCommand cmd = new SqlCommand())
       {
           string txt = "UPDATE tbl_Test_Data SET f_date=getdate() WHERE Age>80;";
           txt += "SELECT Id,Name,LName,f_date,flag,Age,amount FROM [Northwind].[dbo].[tbl_Test_Data]";
           cmd.CommandText = txt;
           cmd.CommandType = CommandType.Text;
           cmd.Connection = cn;

           using (SqlDataAdapter da = new SqlDataAdapter())
           {
               da.SelectCommand = cmd;
               DataTable dt = new DataTable();
               cn.Open();
               da.Fill(dt);
               cn.Close();

               dataGridView2.DataSource = dt;
           }
        }
   }
   sq.Stop();
   label2.Text = sq.Elapsed.TotalMilliseconds.ToString();
}

и для использования цикла for я пишу это:

 Stopwatch sq = new Stopwatch();
 sq.Start();
 using (SqlConnection cn = new SqlConnection("Data Source=.;Initial Catalog=Northwind;Integrated Security=True"))
 {
    using (SqlCommand cmd = new SqlCommand())
    {
       cmd.CommandText = "SELECT Id,Name,LName,f_date,flag,Age,amount FROM [Northwind].[dbo].[tbl_Test_Data]";
       cmd.CommandType = CommandType.Text;
       cmd.Connection = cn;

       using (SqlDataAdapter da = new SqlDataAdapter())
       {
          da.SelectCommand = cmd;
          DataTable dt = new DataTable();
          cn.Open();
          da.Fill(dt);
          cn.Close();

          for (int i = 0; i < dt.Rows.Count; i++)
          {
             if (int.Parse(dt.Rows[i]["Age"].ToString()) > 80)
             {
                dt.Rows[i]["f_date"] = DateTime.Now;
             }
             else
             {
                dt.Rows[i]["f_date"] = DateTime.Now.AddDays(-100);
             }
          }

          dataGridView1.DataSource = dt;
       }
   }
}
sq.Stop();
label1.Text = sq.Elapsed.TotalMilliseconds.ToString();

, но я удивляюсь, что при использовании forцикл занимает меньше времени, чем SQL Server.О (50%).Я тестирую его несколько раз.

Зачем использовать для более короткое время, чем при использовании обновления?

Ответы [ 2 ]

4 голосов
/ 17 января 2012

На самом деле UPDATE имеет дело с блокировками и доступом к диску на уровне сервера, а также обновляет ваши индексы на базовой таблице.

Цикл for не должен иметь дело с этими издержками. Однако изменения, сделанные в цикле for, не видны ни для кого, кроме вашего приложения.

UPDATE внесет изменения для всех других запросов к этой таблице. Изменения цикла for видны только в области приложения с таблицей данных.

Кроме того, также возможно, что если вы запустили эти запросы в том порядке, в котором они размещены, то первый запрос заплатил стоимость ввода-вывода для извлечения страниц с диска, а второй запуск смог извлечь кэшированные страницы. по памяти.

1 голос
/ 17 января 2012

Поскольку в действительности вы НЕ меняете данные на сервере с помощью вашего для случая, вы загружаете данные в свое приложение и меняете их там.

Обновление case сначала изменяет ваши данные на сервере, а затем загружает их в приложение. Очевидно, это занимает больше времени

...