Необходимо выполнить пакетную обработку и выполнить один запрос, который возвращает много строк, вместо множества запросов, каждый из которых возвращает только одну строку (и влечет за собой отдельное обратное обращение к базе данных).
Способ выполнения в SQL Сервер должен переписать запрос для использования табличного параметра (TVP) и передать все критерии поиска (обозначенные как ?
в вашем вопросе) вместе в одном go.
* 1005. * Сначала нам нужно объявить тип, который будет использовать TVP:
CREATE TYPE MyTableSearch AS TABLE (
P bigint NOT NULL
);
И тогда новый запрос будет довольно простым:
SELECT
S,
L
FROM
@input I
JOIN MyTable
ON I.P = MyTable.P;
Основное осложнение на стороне клиента , как связать TVP с запросом. К сожалению, я не знаком с ADO - для чего это стоит, вот как это будет сделано в ADO. NET и C#:
static IEnumerable<(long S, long L)> Find(
SqlConnection conn,
SqlTransaction tran,
IEnumerable<long> input
) {
const string sql = @"
SELECT
S,
L
FROM
@input I
JOIN MyTable
ON I.P = MyTable.P
";
using (var cmd = new SqlCommand(sql, conn, tran)) {
var record = new SqlDataRecord(new SqlMetaData("P", SqlDbType.BigInt));
var param = new SqlParameter("input", SqlDbType.Structured) {
Direction = ParameterDirection.Input,
TypeName = "MyTableSearch",
Value = input.Select(
p => {
record.SetValue(0, p);
return record;
}
)
};
cmd.Parameters.Add(param);
using (var reader = cmd.ExecuteReader())
while (reader.Read())
yield return (reader.GetInt64(0), reader.GetInt64(1));
}
}
Обратите внимание, что мы повторно используем то же самое SqlDataRecord
для всех входных строк, что минимизирует распределение. Это задокументированное поведение, и оно работает, потому что ADO. NET транслирует TVP.
Примечание: [P] уникально в таблице.
Тогда Вы также должны сделать индекс на P уникальным - для корректности и во избежание траты места на юниквитере.