Вот базовый запрос, который опирается на два некластеризованных индекса:
SELECT cc.categoryid, count(*) from company c
INNER JOIN companycategory cc on cc.companyid = c.id
WHERE c.placeid like 'ca_%'
GROUP BY cc.categoryid order by count(*) desc
Когда та же самая база данных размещается на SQL Server 2008, практически на любом оборудовании, она возвращает < 500 мс. Даже при очистке буферов кэша:
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
... это все равно возвращается через ~ 1 секунду на традиционном SQL.
На Azure требуется возврат приблизительно каждые 3,5 секунды.
Некоторые статьи, похоже, показывают, что люди в целом довольны производительностью запросов в SQL Azure. И все же здесь базовый сценарий, когда "очевидная" настройка была исчерпана, и о проблемах с латентностью в сети не говорится. Это просто очень медленно при работе с большими таблицами (компания имеет рейтинг 1.2M, места имеют 7.5K).
Общий размер базы данных не более 4 ГБ. Выбор варианта "Web" и "Enterprise", похоже, не имеет большого значения.
Что мне не хватает?
Это только базовый пример, он только ухудшается с более сложными запросами, все из которых были просмотрены, настроены и хорошо работают -premise.
Здесь план выполнения:
|--Sort(ORDER BY:([Expr1004] DESC))
|--Compute Scalar(DEFINE:([Expr1004]=CONVERT_IMPLICIT(int,[Expr1007],0)))
|--Hash Match(Aggregate, HASH:([cc].[CategoryId]), RESIDUAL:([XX].[dbo].[CompanyCategory].[CategoryId] as [cc].[CategoryId] = [XX].[dbo].[CompanyCategory].[CategoryId] as [cc].[CategoryId]) DEFINE:([Expr1007]=COUNT(*)))
|--Hash Match(Inner Join, HASH:([c].[Id])=([cc].[CompanyId]))
|--Index Scan(OBJECT:([XX].[dbo].[Company].[IX_Company_PlaceId] AS [c]), WHERE:([XX].[dbo].[Company].[PlaceId] as [c].[PlaceId] like N'ca_%'))
|--Index Scan(OBJECT:([XX].[dbo].[CompanyCategory].[IX_CompanyCategory_CompanyId] AS [cc]))
И вот статистика:
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server parse and compile time:
CPU time = 14 ms, elapsed time = 14 ms.
(789 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'CompanyCategory'. Scan count 1, logical reads 5183, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Company'. Scan count 1, logical reads 8710, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
SQL Server Execution Times:
CPU time = 3328 ms, elapsed time = 3299 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
Определения индексов следующие:
CREATE NONCLUSTERED INDEX [IX_Company_PlaceId] ON [dbo].[Company]
(
[PlaceId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
CREATE NONCLUSTERED INDEX [IX_CompanyCategory_CompanyId] ON [dbo].[CompanyCategory]
(
[CompanyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
ALTER TABLE [dbo].[Company] ADD CONSTRAINT [PK_Company_Id] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO