Gestão de cargas de trabalho com classes de recursos no Azure Synapse Analytics
Documentação de orientação para utilizar classes de recursos para gerir a memória e a simultaneidade das consultas do conjunto de SQL do Synapse no Azure Synapse.
O que são classes de recursos
A capacidade de desempenho de uma consulta é determinada pela classe de recursos do utilizador. As classes de recursos são limites de recursos pré-determinados no conjunto de SQL do Synapse que regem os recursos de computação e a simultaneidade para a execução de consultas. As classes de recursos podem ajudá-lo a configurar recursos para as suas consultas ao definir limites no número de consultas que são executadas simultaneamente e nos recursos de computação atribuídos a cada consulta. Há uma troca entre a memória e a simultaneidade.
- As classes de recursos mais pequenas reduzem a memória máxima por consulta, mas aumentam a simultaneidade.
- As classes de recursos maiores aumentam a memória máxima por consulta, mas reduzem a simultaneidade.
Existem dois tipos de classes de recursos:
- Classes de recursos estáticos, que são adequadas para uma maior simultaneidade num tamanho de conjunto de dados que é fixo.
- As classes de recursos dinâmicos, que são adequadas para conjuntos de dados que estão a crescer em tamanho e precisam de um maior desempenho à medida que o nível de serviço é aumentado verticalmente.
As classes de recursos utilizam blocos de simultaneidade para medir o consumo de recursos. Os blocos de simultaneidade são explicados mais à frente neste artigo.
- Para ver a utilização de recursos para as classes de recursos, veja Limites de memória e simultaneidade.
- Para ajustar a classe de recursos, pode executar a consulta num utilizador diferente ou alterar a associação da classe de recursos do utilizador atual .
Classes de recursos estáticos
As classes de recursos estáticos alocam a mesma quantidade de memória, independentemente do nível de desempenho atual, que é medido em unidades do armazém de dados. Uma vez que as consultas obtêm a mesma alocação de memória, independentemente do nível de desempenho, aumentar horizontalmente o armazém de dados permite que mais consultas sejam executadas numa classe de recursos. As classes de recursos estáticos são ideais se o volume de dados for conhecido e constante.
As classes de recursos estáticos são implementadas com estas funções de base de dados predefinidas:
- estáticrc10
- staticrc20
- staticrc30
- staticrc40
- staticrc50
- staticrc60
- staticrc70
- staticrc80
Classes de recursos dinâmicos
As Classes de Recursos Dinâmicas alocam uma quantidade variável de memória consoante o nível de serviço atual. Embora as classes de recursos estáticos sejam benéficas para maior simultaneidade e volumes de dados estáticos, as classes de recursos dinâmicos são mais adequadas para uma quantidade crescente ou variável de dados. Quando aumenta verticalmente para um nível de serviço maior, as consultas obtêm automaticamente mais memória.
As classes de recursos dinâmicos são implementadas com estas funções de base de dados predefinidas:
- smallrc
- mediumrc
- maiorc
- xlargerc
A alocação de memória para cada classe de recursos é a seguinte.
Nível de Serviço | smallrc | mediumrc | maiorc | xlargerc |
---|---|---|---|---|
DW100c | 25% | 25% | 25% | 70% |
DW200c | 12.5% | 12.5% | 22% | 70% |
DW300c | 8% | 10% | 22% | 70% |
DW400c | 6,25% | 10% | 22% | 70% |
DW500c | 5% | 10% | 22% | 70% |
DW1000c para DW30000c |
3% | 10% | 22% | 70% |
Classe de recursos predefinida
Por predefinição, cada utilizador é membro da classe de recursos dinâmica smallrc.
A classe de recursos do administrador de serviços é fixa em smallrc e não pode ser alterada. O administrador de serviços é o utilizador criado durante o processo de aprovisionamento. Neste contexto, o administrador de serviços é o início de sessão especificado para o "Início de sessão de administrador do servidor" ao criar um novo conjunto de SQL do Synapse com um novo servidor.
Nota
Os utilizadores ou grupos definidos como administradores do Active Directory também são administradores de serviços.
Operações da classe de recursos
As classes de recursos foram concebidas para melhorar o desempenho das atividades de gestão e manipulação de dados. As consultas complexas também podem beneficiar da execução numa classe de recursos grande. Por exemplo, o desempenho de consultas para associações grandes e ordenações pode melhorar quando a classe de recursos é grande o suficiente para permitir que a consulta seja executada na memória.
Operações regidas por classes de recursos
Estas operações são regidas por classes de recursos:
- INSERT-SELECT, UPDATE, DELETE
- SELECT (ao consultar tabelas de utilizadores)
- ALTER INDEX - REBUILD or REORGANIZE
- ALTER TABLE REBUILD
- CREATE INDEX
- CRIAR ÍNDICE COLUMNSTORE EM CLUSTER
- CRIAR TABELA COMO SELECT (CTAS)
- Carregamento de dados
- Operações de movimento de dados realizadas pelo Serviço de Movimento de Dados (DMS)
Nota
As instruções SELECT em vistas de gestão dinâmica (DMVs) ou outras vistas do sistema não são regidas por nenhum dos limites de simultaneidade. Pode monitorizar o sistema independentemente do número de consultas em execução no mesmo.
Operações não regidas por classes de recursos
Algumas consultas são sempre executadas na classe de recursos smallrc, apesar de o utilizador ser membro de uma classe de recursos maior. Estas consultas isentas não contam para o limite de simultaneidade. Por exemplo, se o limite de simultaneidade for 16, muitos utilizadores podem selecionar a partir das vistas do sistema sem afetar os blocos de simultaneidade disponíveis.
As seguintes instruções estão isentas de classes de recursos e são sempre executadas em smallrc:
- CRIAR ou LARGAR TABELA
- ALTER TABLE ... COMUTADOR, DIVISÃO ou INTERCALAÇÃO DE PARTIÇÕES
- ALTER INDEX DISABLE
- DROP INDEX
- CRIAR, ATUALIZAR ou REMOVER ESTATÍSTICAS
- TRUNCATE TABLE
- ALTERAR AUTORIZAÇÃO
- CRIAR INÍCIO DE SESSÃO
- CRIAR, ALTERAR ou LARGAR UTILIZADOR
- PROCEDIMENTO CREATE, ALTER ou DROP
- CRIAR ou REMOVER VISTA
- INSERIR VALORES
- SELECIONAR a partir de vistas de sistema e DMVs
- EXPLAIN
- DBCC
Blocos de simultaneidade
Os blocos de simultaneidade são uma forma conveniente de controlar os recursos disponíveis para a execução de consultas. São como bilhetes que compra para reservar lugares num concerto porque os assentos são limitados. O número total de blocos de simultaneidade por armazém de dados é determinado pelo nível de serviço. Antes de uma consulta poder começar a ser executada, tem de ser capaz de reservar blocos de simultaneidade suficientes. Quando uma consulta é concluída, liberta os respetivos blocos de simultaneidade.
- Uma consulta em execução com 10 blocos de simultaneidade pode aceder a 5 vezes mais recursos de computação do que uma consulta em execução com 2 blocos de simultaneidade.
- Se cada consulta necessitar de 10 blocos de simultaneidade e existirem 40 blocos de simultaneidade, apenas 4 consultas podem ser executadas em simultâneo.
Apenas as consultas governadas por recursos consomem blocos de simultaneidade. As consultas do sistema e algumas consultas triviais não consomem blocos. O número exato de blocos de simultaneidade consumidos é determinado pela classe de recursos da consulta.
Ver as classes de recursos
As classes de recursos são implementadas como funções de base de dados predefinidas. Existem dois tipos de classes de recursos: dinâmica e estática. Para ver uma lista das classes de recursos, utilize a seguinte consulta:
SELECT name
FROM sys.database_principals
WHERE name LIKE '%rc%' AND type_desc = 'DATABASE_ROLE';
Alterar a classe de recursos de um utilizador
As classes de recursos são implementadas ao atribuir utilizadores a funções de base de dados. Quando um utilizador executa uma consulta, a consulta é executada com a classe de recursos do utilizador. Por exemplo, se um utilizador for membro da função de base de dados staticrc10, as consultas são executadas com pequenas quantidades de memória. Se um utilizador da base de dados for membro das funções de base de dados xlargerc ou staticrc80, as consultas são executadas com grandes quantidades de memória.
Para aumentar a classe de recursos de um utilizador, utilize sp_addrolemember para adicionar o utilizador a uma função de base de dados de uma classe de recursos grande. O código abaixo adiciona um utilizador à função de base de dados biggerc. Cada pedido obtém 22% da memória do sistema.
EXEC sp_addrolemember 'largerc', 'loaduser';
Para diminuir a classe de recursos, utilize sp_droprolemember. Se "loaduser" não for membro ou outras classes de recursos, entrarão na classe de recursos smallrc predefinida com uma concessão de memória de 3%.
EXEC sp_droprolemember 'largerc', 'loaduser';
Precedência da classe de recursos
Os utilizadores podem ser membros de várias classes de recursos. Quando um utilizador pertence a mais do que uma classe de recursos:
- As classes de recursos dinâmicos têm precedência sobre as classes de recursos estáticos. Por exemplo, se um utilizador for membro de mediumrc(dynamic) e staticrc80 (estático), as consultas são executadas com mediumrc.
- As classes de recursos maiores têm precedência sobre classes de recursos mais pequenas. Por exemplo, se um utilizador for membro de mediumrc e biggerc, as consultas são executadas com biggerc. Da mesma forma, se um utilizador for membro de staticrc20 e statirc80, as consultas são executadas com alocações de recursos staticrc80.
Recomendações
Nota
Considere tirar partido das capacidades de gestão de cargas de trabalho (isolamento, classificação e importância da carga de trabalho) para ter mais controlo sobre a carga de trabalho e o desempenho previsível.
Recomendamos que crie um utilizador dedicado à execução de um tipo específico de consulta ou operação de carregamento. Dê a esse utilizador uma classe de recursos permanente em vez de alterar a classe de recursos com frequência. As classes de recursos estáticos têm um maior controlo geral sobre a carga de trabalho, pelo que sugerimos que utilize classes de recursos estáticos antes de considerar as classes de recursos dinâmicos.
Classes de recursos para carregar utilizadores
CREATE TABLE
utiliza índices columnstore em cluster por predefinição. Comprimir dados para um índice columnstore é uma operação intensiva em termos de memória e a pressão da memória pode reduzir a qualidade do índice. A pressão da memória pode levar à necessidade de uma classe de recursos superior ao carregar dados. Para garantir que as cargas têm memória suficiente, pode criar um utilizador designado para executar cargas e atribuir esse utilizador a uma classe de recursos superior.
A memória necessária para processar cargas de forma eficiente depende da natureza da tabela carregada e do tamanho dos dados. Para obter mais informações sobre os requisitos de memória, veja Maximizar a qualidade do grupo de linhas.
Depois de determinar o requisito de memória, escolha se pretende atribuir o utilizador de carga a uma classe de recursos estática ou dinâmica.
- Utilize uma classe de recursos estática quando os requisitos de memória da tabela estiverem dentro de um intervalo específico. As cargas são executadas com a memória adequada. Quando dimensiona o armazém de dados, as cargas não precisam de mais memória. Ao utilizar uma classe de recursos estáticos, as alocações de memória permanecem constantes. Esta consistência conserva a memória e permite que mais consultas sejam executadas em simultâneo. Recomendamos que as novas soluções utilizem primeiro as classes de recursos estáticos, uma vez que estas fornecem um maior controlo.
- Utilize uma classe de recursos dinâmica quando os requisitos de memória da tabela variam bastante. As cargas podem exigir mais memória do que o nível atual de DWU ou cDWU proporciona. O dimensionamento do armazém de dados adiciona mais memória às operações de carregamento, o que permite que as cargas sejam executadas mais rapidamente.
Classes de recursos para consultas
Algumas consultas consomem muita computação e outras não.
- Escolha uma classe de recursos dinâmica quando as consultas são complexas, mas não precisa de uma simultaneidade elevada. Por exemplo, gerar relatórios diários ou semanais é uma necessidade ocasional de recursos. Se os relatórios estiverem a processar grandes quantidades de dados, o dimensionamento do armazém de dados fornece mais memória à classe de recursos existente do utilizador.
- Escolha uma classe de recursos estática quando as expectativas de recursos variam ao longo do dia. Por exemplo, uma classe de recursos estáticos funciona bem quando o armazém de dados é consultado por muitas pessoas. Ao dimensionar o armazém de dados, a quantidade de memória alocada ao utilizador não é alterada. Consequentemente, mais consultas podem ser executadas em paralelo no sistema.
As concessões de memória adequadas dependem de muitos fatores, como a quantidade de dados consultados, a natureza dos esquemas de tabela e vários predicados de associações, seleção e grupo. Em geral, a alocação de mais memória permite que as consultas sejam concluídas mais rapidamente, mas reduz a simultaneidade geral. Se a simultaneidade não for um problema, a sobrealocação da memória não prejudicará o débito.
Para otimizar o desempenho, utilize classes de recursos diferentes. A secção seguinte fornece um procedimento armazenado que o ajuda a descobrir a melhor classe de recursos.
Código de exemplo para encontrar a melhor classe de recursos
Pode utilizar o seguinte procedimento armazenado especificado para determinar a simultaneidade e a concessão de memória por classe de recursos num determinado SLO e a melhor classe de recursos para operações CCI intensivas de memória na tabela CCI não particionada numa determinada classe de recursos:
Eis o objetivo deste procedimento armazenado:
- Para ver a simultaneidade e a concessão de memória por classe de recursos num determinado SLO. O utilizador tem de fornecer NULL para o esquema e o nome da tabela, conforme mostrado neste exemplo.
- Para ver a melhor classe de recursos para as operações de CCI com muita memória (carga, tabela de cópia, índice de reconstrução, etc.) numa tabela CCI não particionada numa determinada classe de recursos. O proc armazenado utiliza o esquema de tabela para descobrir a concessão de memória necessária.
Restrições de Dependências &
- Este procedimento armazenado não foi concebido para calcular o requisito de memória para uma tabela cci particionada.
- Este procedimento armazenado não tem em conta os requisitos de memória para a parte SELECT de CTAS/INSERT-SELECT e pressupõe que é um SELECT.
- Este procedimento armazenado utiliza uma tabela temporária, que está disponível na sessão onde este procedimento armazenado foi criado.
- Este procedimento armazenado depende das ofertas atuais (por exemplo, configuração de hardware, configuração do DMS) e, se alguma dessas alterações for alterada, este proc armazenado não funcionará corretamente.
- Este procedimento armazenado depende das ofertas de limite de simultaneidade existentes e, se estas alterações forem alteradas, este procedimento armazenado não funcionará corretamente.
- Este procedimento armazenado depende das ofertas de classe de recursos existentes e, se estas alterações forem alteradas, este procedimento armazenado não funcionará corretamente.
Nota
Se não estiver a obter a saída depois de executar o procedimento armazenado com parâmetros fornecidos, poderão existir dois casos.
- O Parâmetro DW contém um valor de SLO inválido
- Em alternativa, não existe nenhuma classe de recursos correspondente para a operação CCI na tabela.
Por exemplo, em DW100c, a concessão de memória mais elevada disponível é de 1 GB e se o esquema da tabela for suficientemente largo para ultrapassar o requisito de 1 GB.
Exemplo de utilização
Sintaxe:
EXEC dbo.prc_workload_management_by_DWU @DWU VARCHAR(7), @SCHEMA_NAME VARCHAR(128), @TABLE_NAME VARCHAR(128)
- @DWU: forneça um parâmetro NULL para extrair a DWU atual da BD DW ou forneça qualquer DWU suportada sob a forma de "DW100c"
- @SCHEMA_NAME: indique um nome de esquema da tabela
- @TABLE_NAME: indique um nome de tabela do interesse
Exemplos de execução deste proc armazenado:
EXEC dbo.prc_workload_management_by_DWU 'DW2000c', 'dbo', 'Table1';
EXEC dbo.prc_workload_management_by_DWU NULL, 'dbo', 'Table1';
EXEC dbo.prc_workload_management_by_DWU 'DW6000c', NULL, NULL;
EXEC dbo.prc_workload_management_by_DWU NULL, NULL, NULL;
A instrução seguinte cria a Tabela1 que é utilizada nos exemplos anteriores.
CREATE TABLE Table1 (a int, b varchar(50), c decimal (18,10), d char(10), e varbinary(15), f float, g datetime, h date);
Definição de procedimento armazenado
-------------------------------------------------------------------------------
-- Dropping prc_workload_management_by_DWU procedure if it exists.
-------------------------------------------------------------------------------
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'prc_workload_management_by_DWU')
DROP PROCEDURE dbo.prc_workload_management_by_DWU
GO
-------------------------------------------------------------------------------
-- Creating prc_workload_management_by_DWU.
-------------------------------------------------------------------------------
CREATE PROCEDURE dbo.prc_workload_management_by_DWU
(@DWU VARCHAR(8),
@SCHEMA_NAME VARCHAR(128),
@TABLE_NAME VARCHAR(128)
)
AS
IF @DWU IS NULL
BEGIN
-- Selecting proper DWU for the current DB if not specified.
SELECT @DWU = 'DW'+ CAST(CASE WHEN Mem> 4 THEN Nodes*500
ELSE Mem*100
END AS VARCHAR(10)) +'c'
FROM (
SELECT Nodes=count(distinct n.pdw_node_id), Mem=max(i.committed_target_kb/1000/1000/60)
FROM sys.dm_pdw_nodes n
CROSS APPLY sys.dm_pdw_nodes_os_sys_info i
WHERE type = 'COMPUTE')A
END
-- Dropping temp table if exists.
IF OBJECT_ID('tempdb..#ref') IS NOT NULL
BEGIN
DROP TABLE #ref;
END;
-- Creating ref. temp table (CTAS) to hold mapping info.
CREATE TABLE #ref
WITH (DISTRIBUTION = ROUND_ROBIN)
AS
WITH
-- Creating concurrency slots mapping for various DWUs.
alloc
AS
(
SELECT 'DW100c' AS DWU,4 AS max_queries,4 AS max_slots,1 AS slots_used_smallrc,1 AS slots_used_mediumrc,2 AS slots_used_largerc,4 AS slots_used_xlargerc,1 AS slots_used_staticrc10,2 AS slots_used_staticrc20,4 AS slots_used_staticrc30,4 AS slots_used_staticrc40,4 AS slots_used_staticrc50,4 AS slots_used_staticrc60,4 AS slots_used_staticrc70,4 AS slots_used_staticrc80
UNION ALL
SELECT 'DW200c',8,8,1,2,4,8,1,2,4,8,8,8,8,8
UNION ALL
SELECT 'DW300c',12,12,1,2,4,8,1,2,4,8,8,8,8,8
UNION ALL
SELECT 'DW400c',16,16,1,4,8,16,1,2,4,8,16,16,16,16
UNION ALL
SELECT 'DW500c',20,20,1,4,8,16,1,2,4,8,16,16,16,16
UNION ALL
SELECT 'DW1000c',32,40,1,4,8,28,1,2,4,8,16,32,32,32
UNION ALL
SELECT 'DW1500c',32,60,1,6,13,42,1,2,4,8,16,32,32,32
UNION ALL
SELECT 'DW2000c',48,80,2,8,17,56,1,2,4,8,16,32,64,64
UNION ALL
SELECT 'DW2500c',48,100,3,10,22,70,1,2,4,8,16,32,64,64
UNION ALL
SELECT 'DW3000c',64,120,3,12,26,84,1,2,4,8,16,32,64,64
UNION ALL
SELECT 'DW5000c',64,200,6,20,44,140,1,2,4,8,16,32,64,128
UNION ALL
SELECT 'DW6000c',128,240,7,24,52,168,1,2,4,8,16,32,64,128
UNION ALL
SELECT 'DW7500c',128,300,9,30,66,210,1,2,4,8,16,32,64,128
UNION ALL
SELECT 'DW10000c',128,400,12,40,88,280,1,2,4,8,16,32,64,128
UNION ALL
SELECT 'DW15000c',128,600,18,60,132,420,1,2,4,8,16,32,64,128
UNION ALL
SELECT 'DW30000c',128,1200,36,120,264,840,1,2,4,8,16,32,64,128
)
-- Creating workload mapping to their corresponding slot consumption and default memory grant.
,map
AS
(
SELECT CONVERT(varchar(20), 'SloDWGroupSmall') AS wg_name, slots_used_smallrc AS slots_used FROM alloc WHERE DWU = @DWU
UNION ALL
SELECT CONVERT(varchar(20), 'SloDWGroupMedium') AS wg_name, slots_used_mediumrc AS slots_used FROM alloc WHERE DWU = @DWU
UNION ALL
SELECT CONVERT(varchar(20), 'SloDWGroupLarge') AS wg_name, slots_used_largerc AS slots_used FROM alloc WHERE DWU = @DWU
UNION ALL
SELECT CONVERT(varchar(20), 'SloDWGroupXLarge') AS wg_name, slots_used_xlargerc AS slots_used FROM alloc WHERE DWU = @DWU
UNION ALL
SELECT 'SloDWGroupC00',1
UNION ALL
SELECT 'SloDWGroupC01',2
UNION ALL
SELECT 'SloDWGroupC02',4
UNION ALL
SELECT 'SloDWGroupC03',8
UNION ALL
SELECT 'SloDWGroupC04',16
UNION ALL
SELECT 'SloDWGroupC05',32
UNION ALL
SELECT 'SloDWGroupC06',64
UNION ALL
SELECT 'SloDWGroupC07',128
)
-- Creating ref based on current / asked DWU.
, ref
AS
(
SELECT a1.*
, m1.wg_name AS wg_name_smallrc
, m1.slots_used * 250 AS tgt_mem_grant_MB_smallrc
, m2.wg_name AS wg_name_mediumrc
, m2.slots_used * 250 AS tgt_mem_grant_MB_mediumrc
, m3.wg_name AS wg_name_largerc
, m3.slots_used * 250 AS tgt_mem_grant_MB_largerc
, m4.wg_name AS wg_name_xlargerc
, m4.slots_used * 250 AS tgt_mem_grant_MB_xlargerc
, m5.wg_name AS wg_name_staticrc10
, m5.slots_used * 250 AS tgt_mem_grant_MB_staticrc10
, m6.wg_name AS wg_name_staticrc20
, m6.slots_used * 250 AS tgt_mem_grant_MB_staticrc20
, m7.wg_name AS wg_name_staticrc30
, m7.slots_used * 250 AS tgt_mem_grant_MB_staticrc30
, m8.wg_name AS wg_name_staticrc40
, m8.slots_used * 250 AS tgt_mem_grant_MB_staticrc40
, m9.wg_name AS wg_name_staticrc50
, m9.slots_used * 250 AS tgt_mem_grant_MB_staticrc50
, m10.wg_name AS wg_name_staticrc60
, m10.slots_used * 250 AS tgt_mem_grant_MB_staticrc60
, m11.wg_name AS wg_name_staticrc70
, m11.slots_used * 250 AS tgt_mem_grant_MB_staticrc70
, m12.wg_name AS wg_name_staticrc80
, m12.slots_used * 250 AS tgt_mem_grant_MB_staticrc80
FROM alloc a1
JOIN map m1 ON a1.slots_used_smallrc = m1.slots_used and m1.wg_name = 'SloDWGroupSmall'
JOIN map m2 ON a1.slots_used_mediumrc = m2.slots_used and m2.wg_name = 'SloDWGroupMedium'
JOIN map m3 ON a1.slots_used_largerc = m3.slots_used and m3.wg_name = 'SloDWGroupLarge'
JOIN map m4 ON a1.slots_used_xlargerc = m4.slots_used and m4.wg_name = 'SloDWGroupXLarge'
JOIN map m5 ON a1.slots_used_staticrc10 = m5.slots_used and m5.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m6 ON a1.slots_used_staticrc20 = m6.slots_used and m6.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m7 ON a1.slots_used_staticrc30 = m7.slots_used and m7.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m8 ON a1.slots_used_staticrc40 = m8.slots_used and m8.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m9 ON a1.slots_used_staticrc50 = m9.slots_used and m9.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m10 ON a1.slots_used_staticrc60 = m10.slots_used and m10.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m11 ON a1.slots_used_staticrc70 = m11.slots_used and m11.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m12 ON a1.slots_used_staticrc80 = m12.slots_used and m12.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
WHERE a1.DWU = @DWU
)
SELECT DWU
, max_queries
, max_slots
, slots_used
, wg_name
, tgt_mem_grant_MB
, up1 as rc
, (ROW_NUMBER() OVER(PARTITION BY DWU ORDER BY DWU)) as rc_id
FROM
(
SELECT DWU
, max_queries
, max_slots
, slots_used
, wg_name
, tgt_mem_grant_MB
, REVERSE(SUBSTRING(REVERSE(wg_names),1,CHARINDEX('_',REVERSE(wg_names),1)-1)) as up1
, REVERSE(SUBSTRING(REVERSE(tgt_mem_grant_MBs),1,CHARINDEX('_',REVERSE(tgt_mem_grant_MBs),1)-1)) as up2
, REVERSE(SUBSTRING(REVERSE(slots_used_all),1,CHARINDEX('_',REVERSE(slots_used_all),1)-1)) as up3
FROM ref AS r1
UNPIVOT
(
wg_name FOR wg_names IN (wg_name_smallrc,wg_name_mediumrc,wg_name_largerc,wg_name_xlargerc,
wg_name_staticrc10, wg_name_staticrc20, wg_name_staticrc30, wg_name_staticrc40, wg_name_staticrc50,
wg_name_staticrc60, wg_name_staticrc70, wg_name_staticrc80)
) AS r2
UNPIVOT
(
tgt_mem_grant_MB FOR tgt_mem_grant_MBs IN (tgt_mem_grant_MB_smallrc,tgt_mem_grant_MB_mediumrc,
tgt_mem_grant_MB_largerc,tgt_mem_grant_MB_xlargerc, tgt_mem_grant_MB_staticrc10, tgt_mem_grant_MB_staticrc20,
tgt_mem_grant_MB_staticrc30, tgt_mem_grant_MB_staticrc40, tgt_mem_grant_MB_staticrc50,
tgt_mem_grant_MB_staticrc60, tgt_mem_grant_MB_staticrc70, tgt_mem_grant_MB_staticrc80)
) AS r3
UNPIVOT
(
slots_used FOR slots_used_all IN (slots_used_smallrc,slots_used_mediumrc,slots_used_largerc,
slots_used_xlargerc, slots_used_staticrc10, slots_used_staticrc20, slots_used_staticrc30,
slots_used_staticrc40, slots_used_staticrc50, slots_used_staticrc60, slots_used_staticrc70,
slots_used_staticrc80)
) AS r4
) a
WHERE up1 = up2
AND up1 = up3
;
-- Getting current info about workload groups.
WITH
dmv
AS
(
SELECT
rp.name AS rp_name
, rp.max_memory_kb*1.0/1048576 AS rp_max_mem_GB
, (rp.max_memory_kb*1.0/1024)
*(request_max_memory_grant_percent/100) AS max_memory_grant_MB
, (rp.max_memory_kb*1.0/1048576)
*(request_max_memory_grant_percent/100) AS max_memory_grant_GB
, wg.name AS wg_name
, wg.importance AS importance
, wg.request_max_memory_grant_percent AS request_max_memory_grant_percent
FROM sys.dm_pdw_nodes_resource_governor_workload_groups wg
JOIN sys.dm_pdw_nodes_resource_governor_resource_pools rp ON wg.pdw_node_id = rp.pdw_node_id
AND wg.pool_id = rp.pool_id
WHERE rp.name = 'SloDWPool'
GROUP BY
rp.name
, rp.max_memory_kb
, wg.name
, wg.importance
, wg.request_max_memory_grant_percent
)
-- Creating resource class name mapping.
,names
AS
(
SELECT 'smallrc' as resource_class, 1 as rc_id
UNION ALL
SELECT 'mediumrc', 2
UNION ALL
SELECT 'largerc', 3
UNION ALL
SELECT 'xlargerc', 4
UNION ALL
SELECT 'staticrc10', 5
UNION ALL
SELECT 'staticrc20', 6
UNION ALL
SELECT 'staticrc30', 7
UNION ALL
SELECT 'staticrc40', 8
UNION ALL
SELECT 'staticrc50', 9
UNION ALL
SELECT 'staticrc60', 10
UNION ALL
SELECT 'staticrc70', 11
UNION ALL
SELECT 'staticrc80', 12
)
,base AS
( SELECT schema_name
, table_name
, SUM(column_count) AS column_count
, ISNULL(SUM(short_string_column_count),0) AS short_string_column_count
, ISNULL(SUM(long_string_column_count),0) AS long_string_column_count
FROM ( SELECT sm.name AS schema_name
, tb.name AS table_name
, COUNT(co.column_id) AS column_count
, CASE WHEN co.system_type_id IN (36,43,106,108,165,167,173,175,231,239)
AND co.max_length <= 32
THEN COUNT(co.column_id)
END AS short_string_column_count
, CASE WHEN co.system_type_id IN (165,167,173,175,231,239)
AND co.max_length > 32 and co.max_length <=8000
THEN COUNT(co.column_id)
END AS long_string_column_count
FROM sys.schemas AS sm
JOIN sys.tables AS tb on sm.[schema_id] = tb.[schema_id]
JOIN sys.columns AS co ON tb.[object_id] = co.[object_id]
WHERE tb.name = @TABLE_NAME AND sm.name = @SCHEMA_NAME
GROUP BY sm.name
, tb.name
, co.system_type_id
, co.max_length ) a
GROUP BY schema_name
, table_name
)
, size AS
(
SELECT schema_name
, table_name
, 75497472 AS table_overhead
, column_count*1048576*8 AS column_size
, short_string_column_count*1048576*32 AS short_string_size, (long_string_column_count*16777216) AS long_string_size
FROM base
UNION
SELECT CASE WHEN COUNT(*) = 0 THEN 'EMPTY' END as schema_name
,CASE WHEN COUNT(*) = 0 THEN 'EMPTY' END as table_name
,CASE WHEN COUNT(*) = 0 THEN 0 END as table_overhead
,CASE WHEN COUNT(*) = 0 THEN 0 END as column_size
,CASE WHEN COUNT(*) = 0 THEN 0 END as short_string_size
,CASE WHEN COUNT(*) = 0 THEN 0 END as long_string_size
FROM base
)
, load_multiplier as
(
SELECT CASE
WHEN FLOOR(8 * (CAST (CAST(REPLACE(REPLACE(@DWU,'DW',''),'c','') AS INT) AS FLOAT)/6000)) > 0
AND CHARINDEX(@DWU,'c')=0
THEN FLOOR(8 * (CAST (CAST(REPLACE(REPLACE(@DWU,'DW',''),'c','') AS INT) AS FLOAT)/6000))
ELSE 1
END AS multiplication_factor
)
SELECT r1.DWU
, schema_name
, table_name
, rc.resource_class as closest_rc_in_increasing_order
, max_queries_at_this_rc = CASE
WHEN (r1.max_slots / r1.slots_used > r1.max_queries)
THEN r1.max_queries
ELSE r1.max_slots / r1.slots_used
END
, r1.max_slots as max_concurrency_slots
, r1.slots_used as required_slots_for_the_rc
, r1.tgt_mem_grant_MB as rc_mem_grant_MB
, CAST((table_overhead*1.0+column_size+short_string_size+long_string_size)*multiplication_factor/1048576 AS DECIMAL(18,2)) AS est_mem_grant_required_for_cci_operation_MB
FROM size
, load_multiplier
, #ref r1, names rc
WHERE r1.rc_id=rc.rc_id
AND CAST((table_overhead*1.0+column_size+short_string_size+long_string_size)*multiplication_factor/1048576 AS DECIMAL(18,2)) < r1.tgt_mem_grant_MB
ORDER BY ABS(CAST((table_overhead*1.0+column_size+short_string_size+long_string_size)*multiplication_factor/1048576 AS DECIMAL(18,2)) - r1.tgt_mem_grant_MB)
GO
Passos seguintes
Para obter mais informações sobre a gestão de utilizadores e segurança da base de dados, veja Proteger uma base de dados no Synapse SQL. Para obter mais informações sobre como classes de recursos maiores podem melhorar a qualidade do índice columnstore em cluster, veja Otimizações de memória para compressão columnstore.