В поле, на котором выполняется этот запрос, находится выделенный сервер, работающий в центре обработки данных.
AMD Opteron 1354 Quad-Core 2,20 ГГц 2 ГБ ОЗУ Windows Server 2008 x64 (Да, я знаю, что у меня всего 2 ГБ ОЗУ, я обновляюсь до 8 ГБ, когда проект идет в прямом эфире).
Итак, я прошел и создал 250 000 фиктивных строк в таблице, чтобы действительно стресс протестировал некоторые запросы, которые генерирует LINQ to SQL, и убедитесь, что они не ужасны, и я заметил, что один из них занимал абсурдное количество времени.
У меня был этот запрос до 17 секунд с индексами, но я удалил их ради этого ответа, чтобы перейти от начала до конца. Только индексы - это первичные ключи.
Stories table --
[ID] [int] IDENTITY(1,1) NOT NULL,
[UserID] [int] NOT NULL,
[CategoryID] [int] NOT NULL,
[VoteCount] [int] NOT NULL,
[CommentCount] [int] NOT NULL,
[Title] [nvarchar](96) NOT NULL,
[Description] [nvarchar](1024) NOT NULL,
[CreatedAt] [datetime] NOT NULL,
[UniqueName] [nvarchar](96) NOT NULL,
[Url] [nvarchar](512) NOT NULL,
[LastActivityAt] [datetime] NOT NULL,
Categories table --
[ID] [int] IDENTITY(1,1) NOT NULL,
[ShortName] [nvarchar](8) NOT NULL,
[Name] [nvarchar](64) NOT NULL,
Users table --
[ID] [int] IDENTITY(1,1) NOT NULL,
[Username] [nvarchar](32) NOT NULL,
[Password] [nvarchar](64) NOT NULL,
[Email] [nvarchar](320) NOT NULL,
[CreatedAt] [datetime] NOT NULL,
[LastActivityAt] [datetime] NOT NULL,
В настоящее время в базе данных есть 1 пользователь, 1 категория и 250 000 рассказов, и я попытался запустить этот запрос.
SELECT TOP(10) *
FROM Stories
INNER JOIN Categories ON Categories.ID = Stories.CategoryID
INNER JOIN Users ON Users.ID = Stories.UserID
ORDER BY Stories.LastActivityAt
Запуск занимает 52 секунды, загрузка процессора колеблется на 2-3%, Membery - 1,1 ГБ, 900 МБ - бесплатно, но использование Диска выходит из-под контроля. Это @100 МБ/с с 2/3 того, что записывается в tempdb.mdf, а остальное - из tempdb.mdf.
Теперь для интересной части...
SELECT TOP(10) *
FROM Stories
INNER JOIN Categories ON Categories.ID = Stories.CategoryID
INNER JOIN Users ON Users.ID = Stories.UserID
SELECT TOP(10) *
FROM Stories
INNER JOIN Users ON Users.ID = Stories.UserID
ORDER BY Stories.LastActivityAt
SELECT TOP(10) *
FROM Stories
INNER JOIN Categories ON Categories.ID = Stories.CategoryID
ORDER BY Stories.LastActivityAt
Все три запроса почти мгновенно.
Exec планирует первый запрос.
http://i43.tinypic.com/xp6gi1.png
Exec планирует другие 3 запроса (в порядке).
http://i43.tinypic.com/30124bp.png
http://i44.tinypic.com/13yjml1.png
http://i43.tinypic.com/33ue7fb.png
Любая помощь будет высоко оценена.
План Exec после добавления индексов (до 17 секунд снова).
http://i39.tinypic.com/2008ytx.png
Я получил много полезной обратной связи от всех, и я благодарю вас, я попробовал новый подход к этому. Я запрашиваю истории, в которых я нуждаюсь, а затем в отдельных запросах получаю категории и пользователи и с 3 запросами занимает всего 250 мс... Я не понимаю эту проблему, но если она работает и на 250 мс не меньше, придерживайтесь этого. Вот код, который я использовал для проверки этого.
DBDataContext db = new DBDataContext();
Console.ReadLine();
Stopwatch sw = Stopwatch.StartNew();
var stories = db.Stories.OrderBy(s => s.LastActivityAt).Take(10).ToList();
var storyIDs = stories.Select(c => c.ID);
var categories = db.Categories.Where(c => storyIDs.Contains(c.ID)).ToList();
var users = db.Users.Where(u => storyIDs.Contains(u.ID)).ToList();
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);