Not*_*ple 14 sql sql-server-2008-r2
我有一个SQL表,我想按ID选择多行.例如,我想从我的表中获取ID为1,5和9的行.
我一直在使用类似于下面的WHERE IN语句执行此操作:
SELECT [Id]
FROM [MyTable]
WHERE [Id] IN (1,5,9)
Run Code Online (Sandbox Code Playgroud)
然而,对于"IN"子句中的大量项目来说,这是非常缓慢的
下面是使用1,000,000行的表中的where in选择行的一些性能数据
Querying for 1 random keys (where in) took 0ms
Querying for 1000 random keys (where in) took 46ms
Querying for 2000 random keys (where in) took 94ms
Querying for 3000 random keys (where in) took 249ms
Querying for 4000 random keys (where in) took 316ms
Querying for 5000 random keys (where in) took 391ms
Querying for 6000 random keys (where in) took 466ms
Querying for 7000 random keys (where in) took 552ms
Querying for 8000 random keys (where in) took 644ms
Querying for 9000 random keys (where in) took 743ms
Querying for 10000 random keys (where in) took 853ms
Run Code Online (Sandbox Code Playgroud)
有没有比使用WHERE IN更快的方法来做到这一点.
我们不能进行连接,因为这是在断开连接的系统之间.
我听说内存中的临时表连接到MYSQL中的数据可能会更快但是从我的研究中MSSQL没有内存表选项,即便这样也不会在插入时容易出现完全相同的索引扫描作为WHERE IN的临时表有哪些?
编辑:
此表的ID为PK,因此具有默认的PK索引,cf
CREATE TABLE [dbo].[Entities](
[Id] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_dbo.Entities] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
执行计划

这是一个控制台应用程序的GIST,可以产生这些性能结果https://gist.github.com/lukemcgregor/5914774
编辑2 我创建了一个函数,它从逗号分隔的字符串创建临时表,然后与该表连接.它更快,但我认为主要是因为解析查询的问题在哪里
Querying for 1 random keys took 1ms
Querying for 1000 random keys took 34ms
Querying for 2000 random keys took 69ms
Querying for 3000 random keys took 111ms
Querying for 4000 random keys took 143ms
Querying for 5000 random keys took 182ms
Querying for 6000 random keys took 224ms
Querying for 7000 random keys took 271ms
Querying for 8000 random keys took 315ms
Querying for 9000 random keys took 361ms
Querying for 10000 random keys took 411ms
Run Code Online (Sandbox Code Playgroud)
好的,所以我通过定义一个表类型,然后将该类型直接传递给查询并加入到它中,让它变得非常快.
在SQL中
CREATE TYPE [dbo].[IntTable] AS TABLE(
[value] [int] NULL
)
Run Code Online (Sandbox Code Playgroud)
在代码中
DataTable dataTable = new DataTable("mythang");
dataTable.Columns.Add("value", typeof(Int32));
toSelect.ToList().ForEach(selectItem => dataTable.Rows.Add(selectItem));
using (SqlCommand command = new SqlCommand(
@"SELECT *
FROM [dbo].[Entities] e
INNER JOIN @ids on e.id = value", con))
{
var parameter = command.Parameters.AddWithValue("@ids", dataTable);
parameter.SqlDbType = System.Data.SqlDbType.Structured;
parameter.TypeName = "IntTable";
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
results.Add(reader.GetInt32(0));
}
}
}
Run Code Online (Sandbox Code Playgroud)
这会产生以下结果
Querying for 1 random keys (passed in table value) took 2ms
Querying for 1000 random keys (passed in table value) took 3ms
Querying for 2000 random keys (passed in table value) took 4ms
Querying for 3000 random keys (passed in table value) took 6ms
Querying for 4000 random keys (passed in table value) took 8ms
Querying for 5000 random keys (passed in table value) took 9ms
Querying for 6000 random keys (passed in table value) took 11ms
Querying for 7000 random keys (passed in table value) took 13ms
Querying for 8000 random keys (passed in table value) took 17ms
Querying for 9000 random keys (passed in table value) took 16ms
Querying for 10000 random keys (passed in table value) took 18ms
Run Code Online (Sandbox Code Playgroud)