Почему поиск по индексированному столбцу не выполняется быстрее, чем сравнение строк?C#

Место общения программистов C#
Ответить
Anonymous
 Почему поиск по индексированному столбцу не выполняется быстрее, чем сравнение строк?

Сообщение Anonymous »

Меня попросили продемонстрировать, насколько быстрее поиск по индексированному столбцу, чем поиск по строковому префиксу, поэтому я создал быстрый тест, но результаты оказались неожиданными, и я не понимаю, почему.
База данных состоит из одной таблицы (

Код: Выделить всё

Products
) со столбцами ProductName и Brand и несколькими другими столбцами, просто чтобы увеличить объем данных с помощью индекса по бренду:

Код: Выделить всё

CREATE TABLE [dbo].[Products]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[ProductName] [nvarchar](500) NOT NULL,
[Brand] [nvarchar](100) NOT NULL,
[Field1] [nvarchar](50) NULL,
[Field2] [nvarchar](50) NULL,
[Field3] [nvarchar](50) NULL,
[Field4] [nvarchar](50) NULL,
[Field5] [nvarchar](50) NULL,
Ix_Brands index(Brand),

CONSTRAINT [PK_Products]
PRIMARY KEY CLUSTERED ([ID] ASC)
)
Затем я получаю продукты по брендам, используя 4 разных метода и время, которое занимает каждый из них.

Код: Выделить всё

using System;
using System.Data;
using System.Data.SqlClient;
using System.Linq;

namespace SpeedTest
{
internal class Program
{
static void Main(string[] args)
{
var connectionString = "data source=.";
string[] Brands = new string[] { "Tesco", "Asda", "Boots", "Morrisons", "Amazon", "Ebay" };

var rnd = new Random();
DateTime startTime;

using (var con = new SqlConnection(connectionString))
{
var cmd = new SqlCommand("delete from products", con);
con.Open();
cmd.ExecuteNonQuery();

Console.WriteLine("Creating 100,000 products");

for (int i = 0; i < 100000; i++)
{
var brand = Brands[rnd.Next(Brands.Length)];
cmd.CommandText = $"insert into products(productName, brand, field1, field2, field3, field4, field5) values ('{brand}_{Guid.NewGuid()}', '{brand}', '{Guid.NewGuid()}', '{Guid.NewGuid()}', '{Guid.NewGuid()}', '{Guid.NewGuid()}', '{Guid.NewGuid()}')";
cmd.ExecuteNonQuery();
}

Console.WriteLine("Getting products by brand via ADO and product name prefix");
startTime = DateTime.Now;

foreach (var brand in Brands)
{
cmd.CommandText = $"select * from products where productName like '{brand}_%'";
var da = new SqlDataAdapter(cmd);
var dt = new DataTable();
da.Fill(dt);
}

Console.WriteLine($"Time taken: {(DateTime.Now - startTime).TotalMilliseconds}ms");
Console.WriteLine("Getting products by brand via ADO and indexed brand column");
startTime = DateTime.Now;

foreach (var brand in Brands)
{
cmd.CommandText = $"select * from products where brand='{brand}'";
var da = new SqlDataAdapter(cmd);
var dt = new DataTable();
da.Fill(dt);
}

Console.WriteLine($"Time taken: {(DateTime.Now - startTime).TotalMilliseconds}ms");
con.Close();
}

var db = new SpeedTestEntities();
Console.WriteLine("Getting products by brand via entity framework and product name prefix");
startTime = DateTime.Now;

foreach (var brand in Brands)
{
var products = db.Products.Where(p => p.ProductName.StartsWith(brand + "_")).ToList();
}

Console.WriteLine($"Time taken: {(DateTime.Now - startTime).TotalMilliseconds}ms");
Console.WriteLine("Getting products by brand via entity framework and indexed brand column");
startTime = DateTime.Now;

foreach (var brand in Brands)
{
var products = db.Products.Where(p =>  p.Brand.Equals(brand, StringComparison.OrdinalIgnoreCase)).ToList();
}

Console.WriteLine($"Time taken: {(DateTime.Now - startTime).TotalMilliseconds}ms");
Console.ReadLine();
}
}
}
Результаты Entity Framework были примерно такими, как я ожидал, но результаты ADO показали, что поиск по индексированному столбцу был медленнее, чем по префиксу названия продукта, что, безусловно, не может быть правильным:
р>

Код: Выделить всё

Creating 100,000 products
Getting products by brand via ADO and product name prefix
Time taken: 558.9306ms
Getting products by brand via ADO and indexed brand column
Time taken: 642.5258ms
Getting products by brand via entity framework and product name prefix
Time taken: 3266.8438ms
Getting products by brand via entity framework and indexed brand column
Time taken: 204.932ms
Наверное, я где-то напутал, но не могу понять где. Моя демонстрация того, почему мы должны добавлять индексированные столбцы в таблицы нашей базы данных, а не добавлять префиксы к другим строкам, идет плохо.
Может ли кто-нибудь меня спасти и посмотреть, что здесь происходит?EDIT: оказывается, что оба запроса ADO выполняют сканирование индекса PK_Products. Оба плана выполнения одинаковы. Это меня удивило, и я думал, что добавление индексированного столбца, безусловно, будет быстрее, но, видимо, нет.
План выполнения

Подробнее здесь: https://stackoverflow.com/questions/785 ... comparison
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»