powered by simpleCommunicator - 2.0.41     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
25 сообщений из 25, страница 1 из 1
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39969315
Alexander Us
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вопрос об использовании временных таблиц в .NET приложении.

Пример:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
 Using cn As New SqlConnection("Server=myServerAddress;Database=myDataBase;Trusted_Connection=True;")

            '1: ad hoc query - создаем таблицу
            Using cm As New SqlCommand("create table #T1(C1 int)", cn)
                cm.ExecuteNonQuery()
            End Using

            '2: ad hoc query - заливаем данные (обычно я делаю это через SqlBulkCopy)
            Using cm As New SqlCommand("insert #T1 select 1 C1 union all select 1", cn)
                cm.ExecuteNonQuery()
            End Using

            '3: parameterized query - делаем какой то запрос с использованием временной таблицы. результат передаем клиенту.
            Using cm As New SqlCommand("select count(*) from #T1 where C1 = 1", cn)
                cm.Parameters.Add("X", SqlDbType.Int).Value = 1
                ret = CInt(cm.ExecuteScalar())
            End Using
        End Using


Запросы 1 и 2 будут выполнены как "ad hoc", а запрс 3 как "parameterized" - с использованием sp_executesql.

Однако, я нигде не нашел, что такое поведение описано в документации.
Если MS когда нибудь изменит поведение SqlCommand так, что запросы 1 и 2 будут упауованы в sp_executesql, то использование временных таблиц из .NET кода станет новозможным, а приложение станет неработоспособным.


Т.е.:
  • Можно ли включать такое использование времменных таблиц в приложение и быть уверенным, что со следующим фреймворком это ещё будет работать?
  • Может ли кто привести "тынц" в документацию на SqlCommand: "ad hoc" vs. "parameterized"?
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39969336
Фотография Критик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexander Us,

Интегрируйте всю логику в хранимки, тогда проблем точно не будет.
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39969348
Alexander Us
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Критик
Alexander Us,

Интегрируйте всю логику в хранимки, тогда проблем точно не будет.

Думаю, Вы слишком оптимистичны.

В хранимку конечно можно передать табличный параметер, но для больного объёма данных табличный параметер тормозот жутко.

Для передачи больного объёма данных (как параметра) единственный хороший способ (в смысле быстрый) это использование временной таблицы и заливка в неё балком.
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39969356
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexander Us,

Между коннекшинами они потеряются.

Используй либо глобальные ##temp, либо постоянные таблицы.
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39969360
Alexander Us
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voronin,

- это понятно, поэтому я и использую один коннекшн

- если создание временной таблицы происходит парамеиризорованном запросе (фактически в в sp_executesql) то такая таблица умирает с его окончанием. Что с одним, что с двумя ##.
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39969362
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexander Us
a_voronin,

- это понятно, поэтому я и использую один коннекшн

- если создание временной таблицы происходит парамеиризорованном запросе (фактически в в sp_executesql) то такая таблица умирает с его окончанием. Что с одним, что с двумя ##.


А набить в StringBuilder одну мегапартянку и запустить одним махом -- не вариант?
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39969370
Alexander Us
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voronin,

логика, которую я описал у меня прекрасно работает на "моих" некритичных приложениях.
Но я не знаю, насколько она "кошерна" в том плане, что я не могу явно влиять на то, чтобя запрос выполнялся как ad hoc.

Ещё раз, я делаю так:

В .NET
1) открываем коннекшн
2) создаём временную таблицу ( только ad hoc командой!!! )
3) заливаем в неё кучу данных через SqlBulkCopy
4) выполняем запрос на выборку/изменение с джоином ко временной таблице (этот запрос уже может быть параметризированный)
5) закрываем коннекшн
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39969374
Alexander Us
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voronin
...А набить в StringBuilder одну мегапартянку...

Для человека, раз вкусившего скорость, прелесть и удобство SqlBulkCopy, это если и вариант, то с горючими, горючими слезами.
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39969463
Alexander Us
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В исходном коде от MS для SqlCommand написано :

Код: c#
1.
2.
else if ((System.Data.CommandType.Text == this.CommandType) && (0 == GetParameterCount(_parameters))) {
// Send over SQL Batch command if we are not a stored proc and have no parameters



Будет ли это достаточным основанием считать, что так будет и в следующих версиях .Framework?

Модератор: Тема перенесена из форума "Microsoft SQL Server".
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39969593
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexander Us
Будет ли это достаточным основанием считать, что так будет и в следующих версиях .Framework?

Ни это, ни вообще что-либо не будет достаточным основанием считать, что в следующиих версиях будет и это, и сама SqlCommand, и вообще что угодно. Прецедент с выпиливанием DataTable в Core 1.0 уже был - в 2.0, правда, вернули.
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39969607
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexander Us

2) создаём временную таблицу ( только ad hoc командой!!! )
3) заливаем в неё кучу данных через SqlBulkCopy
4) выполняем запрос на выборку/изменение с джоином ко временной таблице (этот запрос уже может быть параметризированный)


Вот для такой последовательности действий очень хорошо подходить IN-MEMORY SCHEMA_ONLY.

Чего вы ходите вокруг временной таблицы, непонятно.
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39969685
Alexander Us
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voronin
для такой последовательности действий очень хорошо подходить IN-MEMORY SCHEMA_ONLY.
Чего вы ходите вокруг временной таблицы, непонятно.

Дык это для SQL2008 R2 Enterprise :(
Но спасибо за совет, буду иметь ввиду для более новых версий.
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39972375
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voronin
Вот для такой последовательности действий очень хорошо подходить IN-MEMORY SCHEMA_ONLY.

Чего вы ходите вокруг временной таблицы, непонятно.

Ради интереса проверил:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
USE master
GO
CREATE DATABASE InMemDb CONTAINMENT = NONE
ON PRIMARY (
  NAME = N'InMemDb', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\InMemDb.mdf' ,
  SIZE = 275456KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ), 
FILEGROUP [MEMGROUP] CONTAINS MEMORY_OPTIMIZED_DATA  DEFAULT (
  NAME = N'MemDataFile', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\MemDataFile' ,
  MAXSIZE = UNLIMITED
)
LOG ON (
  NAME = N'InMemDb_log',
  FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\InMemDb_log.ldf' ,
  SIZE = 1341696KB , MAXSIZE = 2048GB , FILEGROWTH = 10%
)
GO

use InMemDb
go
create table dbo.NotInMemory (
  id bigint identity not null primary key nonclustered,
  n int not null,
)
go
create table dbo.InMemory (
  id bigint identity NOT NULL,
  n int not null,
  primary key nonclustered hash (id) with (bucket_count = 1048576)
) with (memory_optimized = on, durability = schema_only)
go
select @@version;


Код: plaintext
1.
2.
3.
Microsoft SQL Server 2014 (SP2-CU12) (KB4130489) - 12.0.5589.7 (X64) 
	Jun  9 2018 11:17:15 
	Copyright (c) Microsoft Corporation
	Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
public class Program
{
  public static void Main(string[] args)
    => BenchmarkRunner.Run<Program>();

  [Benchmark]
  public void InMemoryInsert()
  {
    using(var cnn = new SqlConnection("Data Source=.;Initial Catalog=InMemDb;Integrated Security=True"))
    {
      cnn.Open();
      using(var tran = cnn.BeginTransaction())
      {
        using(var cmd = new SqlCommand("insert into dbo.InMemory(n) values(@n)", cnn, tran))
        {
          var p = cmd.Parameters.Add("@n", SqlDbType.Int);
          using(var idr = new IntDataReader())
            while(idr.Read())
            {
              p.Value = idr.GetValue(0);
              cmd.ExecuteNonQuery();
            }
        }
        tran.Commit();
      }
    }
  }

  [Benchmark]
  public void BulkInsert()
  {
    using(var cnn = new SqlConnection("Data Source=.;Initial Catalog=InMemDb;Integrated Security=True"))
    {
      cnn.Open();
      using(var bc = new SqlBulkCopy(cnn))
      {
        bc.DestinationTableName = "dbo.NotInMemory";
        bc.ColumnMappings.Add(0, 1);
        using(var idr = new IntDataReader())
          bc.WriteToServer(idr);
      }
    }
  }

  class IntDataReader : IDataReader
  {
    const int MaxValue = 10000;
    public void Close() => RecordsAffected = MaxValue;
    public void Dispose() => Close();
    public bool Read() => RecordsAffected < MaxValue;
    public int FieldCount => 1;
    public int Depth => 0;
    public bool IsClosed => RecordsAffected >= MaxValue;
    public int RecordsAffected { get; private set; }
    public object GetValue(int i) => RecordsAffected++;

    public string GetName(int i) => throw new NotImplementedException();
    public string GetDataTypeName(int i) => throw new NotImplementedException();
    public Type GetFieldType(int i) => throw new NotImplementedException();
    public int GetValues(object[] values) => throw new NotImplementedException();
    public int GetOrdinal(string name) => throw new NotImplementedException();
    public bool GetBoolean(int i) => throw new NotImplementedException();
    public byte GetByte(int i) => throw new NotImplementedException();
    public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
      => throw new NotImplementedException();
    public char GetChar(int i) => throw new NotImplementedException();
    public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
      => throw new NotImplementedException();
    public Guid GetGuid(int i) => throw new NotImplementedException();
    public short GetInt16(int i) => throw new NotImplementedException();
    public int GetInt32(int i) => throw new NotImplementedException();
    public long GetInt64(int i) => throw new NotImplementedException();
    public float GetFloat(int i) => throw new NotImplementedException();
    public double GetDouble(int i) => throw new NotImplementedException();
    public string GetString(int i) => throw new NotImplementedException();
    public decimal GetDecimal(int i) => throw new NotImplementedException();
    public DateTime GetDateTime(int i) => throw new NotImplementedException();
    public IDataReader GetData(int i) => throw new NotImplementedException();
    public bool IsDBNull(int i) => throw new NotImplementedException();
    public object this[int i] => throw new NotImplementedException();
    public object this[string name] => throw new NotImplementedException();
    public DataTable GetSchemaTable() => throw new NotImplementedException();
    public bool NextResult() => throw new NotImplementedException();
  }
}


Результат:

Код: plaintext
1.
2.
3.
         Method |      Mean |     Error |    StdDev |
--------------- |----------:|----------:|----------:|
 InMemoryInsert | 578.86 ms | 5.4307 ms | 5.0799 ms |
     BulkInsert |  66.25 ms | 0.9006 ms | 0.7520 ms |

Я, пожалуй, пока буду пользоваться SqlBulkCopy.
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39972519
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны

Я, пожалуй, пока буду пользоваться SqlBulkCopy.


А вы сделали совсем не то, что я рекомендовал

Я имел ввиду попробовать

using(var bc = new SqlBulkCopy(cnn))

1) на физической таблице
2) на InMemory таблице

SqlBulkCopy в обоих случаях.

причем попробуйте в 10 - 15 потоках.
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39972520
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voronin
2) на InMemory таблице


А если данных больше чем доступная Memory?
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39972522
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voronin
1) на физической таблице
2) на InMemory таблице

И как в таком случае быть с конкурентным доступом? В тесте я для простоты использовал постоянную таблицу, но вообще предполагалось, что как и у ТС, заливка будет делаться во временную, которая видна только тому, кто делает заливку. А что будет с in-memory?
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39973631
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
a_voronin
2) на InMemory таблице


А если данных больше чем доступная Memory?

А что, если данных больше чем доступно места на дисках?
...
Рейтинг: 0 / 0
Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    #39973632
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexander Us
  • Можно ли включать такое использование времменных таблиц в приложение и быть уверенным, что со следующим фреймворком это ещё будет работать?
  • Можно. У них у первых "послетает" куча кода.
    Alexander Us
  • Может ли кто привести "тынц" в документацию на SqlCommand: "ad hoc" vs. "parameterized"?
  • Нет.
    ...
    Рейтинг: 0 / 0
    Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
        #39973823
    Фотография hVostt
    Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
    Участник
    ЕвгенийВ
    hVostt
    пропущено...


    А если данных больше чем доступная Memory?

    А что, если данных больше чем доступно места на дисках?


    Дисковое пространство можно расширить до десятков ТБ очень дёшево.

    Вопрос актуален.
    ...
    Рейтинг: 0 / 0
    Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
        #39973934
    Alexander Us
    Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
    Участник
    hVostt
    a_voronin
    2) на InMemory таблице


    А если данных больше чем доступная Memory?


    Конечно это зависит от логики Вашего приложения.
    Я обычно использую TempTable в комбинации с SqlBulkcopy для копирования / преобразования данных порциями.
    Так что для меня память не стала бы проблемой.
    ...
    Рейтинг: 0 / 0
    Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
        #39973936
    Фотография hVostt
    Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
    Участник
    Alexander Us
    Конечно это зависит от логики Вашего приложения.
    Я обычно использую TempTable в комбинации с SqlBulkcopy для копирования / преобразования данных порциями.
    Так что для меня память не стала бы проблемой.


    Порции конечно решают... )
    ...
    Рейтинг: 0 / 0
    Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
        #39973953
    Ролг Хупин
    Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
    Участник
    Alexander Us
    Вопрос об использовании временных таблиц в .NET приложении.

    Пример:
    Код: vbnet
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.
    9.
    10.
    11.
    12.
    13.
    14.
    15.
    16.
    17.
    18.
     Using cn As New SqlConnection("Server=myServerAddress;Database=myDataBase;Trusted_Connection=True;")
    
                '1: ad hoc query - создаем таблицу
                Using cm As New SqlCommand("create table #T1(C1 int)", cn)
                    cm.ExecuteNonQuery()
                End Using
    
                '2: ad hoc query - заливаем данные (обычно я делаю это через SqlBulkCopy)
                Using cm As New SqlCommand("insert #T1 select 1 C1 union all select 1", cn)
                    cm.ExecuteNonQuery()
                End Using
    
                '3: parameterized query - делаем какой то запрос с использованием временной таблицы. результат передаем клиенту.
                Using cm As New SqlCommand("select count(*) from #T1 where C1 = 1", cn)
                    cm.Parameters.Add("X", SqlDbType.Int).Value = 1
                    ret = CInt(cm.ExecuteScalar())
                End Using
            End Using
    


    Запросы 1 и 2 будут выполнены как "ad hoc", а запрс 3 как "parameterized" - с использованием sp_executesql.

    Однако, я нигде не нашел, что такое поведение описано в документации.
    Если MS когда нибудь изменит поведение SqlCommand так, что запросы 1 и 2 будут упауованы в sp_executesql, то использование временных таблиц из .NET кода станет новозможным, а приложение станет неработоспособным.


    Т.е.:
    • Можно ли включать такое использование времменных таблиц в приложение и быть уверенным, что со следующим фреймворком это ещё будет работать?
    • Может ли кто привести "тынц" в документацию на SqlCommand: "ad hoc" vs. "parameterized"?

    Что в вашем понимании "следующий фреймворк"?
    ...
    Рейтинг: 0 / 0
    Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
        #39973971
    Alexander Us
    Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
    Участник
    Ролг Хупин
    Что в вашем понимании "следующий фреймворк"?

    То,что больше 4.8 выпущенной в апреле 2019.
    Хотелось бы, чтобы код сохранил работоспособность и с ними.
    ...
    Рейтинг: 0 / 0
    Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
        #39974058
    Ролг Хупин
    Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
    Участник
    Alexander Us
    Ролг Хупин
    Что в вашем понимании "следующий фреймворк"?

    То,что больше 4.8 выпущенной в апреле 2019.
    Хотелось бы, чтобы код сохранил работоспособность и с ними.


    Не помню, чтобы такие несовместимости были в новых фреймворках, ну, это ладно.
    "Следующий": В ноябре выдйет 5.0, основанный на Core

    В вашем примере, что означает "parameterized query" и что такое "Х"?

    Код: c#
    1.
    2.
    3.
    4.
    5.
    '3: parameterized query - делаем какой то запрос с использованием временной таблицы. результат передаем клиенту.
                Using cm As New SqlCommand("select count(*) from #T1 where C1 = 1", cn)
                    cm.Parameters.Add("X", SqlDbType.Int).Value = 1
                    ret = CInt(cm.ExecuteScalar())
                End Using
    
    ...
    Рейтинг: 0 / 0
    Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
        #39974087
    Alexander Us
    Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
    Участник
    Ролг Хупин
    В вашем примере, что означает "parameterized query" и что такое "Х"?


    parameterized query:
    имеется ввиду, что объект SqlCommand получит параметры, следовательно, на SQL Server запрос прийдёт упакованный в sp_executesql.

    что такое "Х":
    да, пример корявый.
    Прости имелось ввиду, что запрос, который использует временную таблицу для выборки или актуализации данных, может иметь параметры.
    ...
    Рейтинг: 0 / 0
    25 сообщений из 25, страница 1 из 1
    Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Временные таблицы и SqlCommand: "ad hoc" vs. "parameterized"
    Целевая тема:
    Создать новую тему:
    Автор:
    Закрыть
    Цитировать
    Найденые пользователи ...
    Разблокировать пользователей ...
    Читали форум (0):
    Пользователи онлайн (0):
    x
    x
    Закрыть


    Просмотр
    0 / 0
    Close
    Debug Console [Select Text]