Lors du développement avec MaxCompute, il peut être nécessaire d'analyser les coûts des comptes et la durée des jobs afin de mieux les planifier et les ajuster. Cette rubrique explique comment utiliser les métadonnées MaxCompute (Information Schema) pour identifier les comptes les plus coûteux et les jobs les plus longs. Vous pouvez également transmettre ces informations à un groupe DingTalk.
Contexte
Les développeurs de données utilisent souvent MaxCompute en mode standard DataWorks. Dans ce mode, MaxCompute enregistre le même compte racine dans Information Schema comme exécuteur pour la plupart des jobs. Seuls quelques jobs sont exécutés par des utilisateurs Resource Access Management (RAM). Il est donc difficile d'analyser les coûts et la durée des jobs pour chaque compte individuel. MaxCompute propose les solutions suivantes :
Coûts des comptes : vous pouvez consulter les détails d'utilisation dans votre facture. Toutefois, cette méthode ne permet pas de lier l'utilisation à des utilisateurs RAM spécifiques. La vue TASKS_HISTORY dans Information Schema enregistre les détails des jobs terminés dans votre projet MaxCompute au cours des 14 derniers jours. Vous pouvez sauvegarder les données de TASKS_HISTORY dans un projet MaxCompute et les utiliser pour identifier les comptes les plus coûteux.
Jobs chronophages : vous pouvez utiliser les données de TASKS_HISTORY pour identifier les jobs les plus longs.
Pour plus d'informations sur les fonctionnalités et les limites d'Information Schema, consultez la section Information Schema au niveau du projet.
Le processus d'analyse des N premiers comptes de facturation et des jobs chronophages est le suivant :
Étape 1 : Obtenir le service Information Schema
Depuis le 1er mars 2024, MaxCompute n'installe plus automatiquement Information Schema au niveau du projet pour les nouveaux projets. Pour interroger les métadonnées, utilisez plutôt Information Schema au niveau du locataire, qui fournit des informations plus complètes. Pour plus d'informations, consultez la section Information Schema au niveau du locataire.
Pour les projets MaxCompute existants, afin d'utiliser le service Information Schema, vous devez installer le package d'autorisations Information Schema en tant que propriétaire du projet ou utilisateur RAM disposant du rôle Super_Administrator. Pour plus d'informations sur l'attribution d'un rôle de gestion à un utilisateur, consultez la section Attribuer un rôle à un utilisateur. Vous pouvez installer le package de l'une des deux manières suivantes :
-
Connectez-vous au client MaxCompute et exécutez la commande suivante :
install package Information_Schema.systables; -
Connectez-vous à la console DataWorks et accédez à la page Ad Hoc Query. Pour plus d'informations, consultez la section Exécuter des instructions SQL dans une requête ad hoc (facultatif). Exécutez la commande suivante :
install package Information_Schema.systables;
Pour analyser les métadonnées de plusieurs projets MaxCompute, installez le package d'autorisations Information Schema pour chaque projet. Insérez ensuite les sauvegardes de métadonnées de tous les projets dans une seule table pour l'analyse.
(Facultatif) Étape 2 : Accorder des autorisations aux utilisateurs autres que le propriétaire du projet
Les vues Information Schema contiennent toutes les données utilisateur au niveau du projet. Par défaut, seul le propriétaire du projet peut accéder à ces données. Si d'autres utilisateurs ou rôles du projet doivent y accéder, vous devez leur accorder des autorisations. Pour plus d'informations, consultez la section Accéder aux ressources entre projets basés sur des packages.
Syntaxe d'octroi des autorisations :
grant <actions> on package Information_Schema.systables to user <user_name>;
grant <actions> on package Information_Schema.systables to role <role_name>;
actions : l'autorisation d'opération à accorder. La valeur est Read.
-
user_name : un compte Alibaba Cloud ou un utilisateur RAM ajouté au projet.
Vous pouvez exécuter la commande
list users;dans le client MaxCompute pour obtenir les comptes utilisateur. -
role_name : un rôle ajouté au projet.
Vous pouvez exécuter la commande
list roles;dans le client MaxCompute pour obtenir le nom du rôle.
Exemple :
grant read on package Information_Schema.systables to user RAM$Bob@aliyun.com:user01;
Étape 3 : Télécharger et sauvegarder les métadonnées
Créez une table de sauvegarde des métadonnées dans votre projet MaxCompute et planifiez une tâche récurrente pour y écrire les métadonnées. Les étapes suivantes fournissent un exemple utilisant le client MaxCompute :
-
Connectez-vous au client MaxCompute et exécutez la commande suivante pour créer une table de sauvegarde des métadonnées.
-- project_name is the name of your MaxCompute project. CREATE TABLE if NOT EXISTS <project_name>.information_history ( task_catalog STRING ,task_schema STRING ,task_name STRING ,task_type STRING ,inst_id STRING ,`status` STRING ,owner_id STRING ,owner_name STRING ,result STRING ,start_time DATETIME ,end_time DATETIME ,input_records BIGINT ,output_records BIGINT ,input_bytes BIGINT ,output_bytes BIGINT ,input_tables STRING ,output_tables STRING ,operation_text STRING ,signature STRING ,complexity DOUBLE ,cost_cpu DOUBLE ,cost_mem DOUBLE ,settings STRING ,ds STRING ); -
Accédez à l'interface Data Studio de DataWorks, créez un nœud ODPS SQL (information_history) et configurez la planification horaire pour écrire périodiquement les données dans la table de sauvegarde information_history. Cliquez ensuite sur l'icône
en haut à gauche pour enregistrer le nœud.Pour plus d'informations, consultez la section Créer un nœud ODPS SQL.
Le code suivant montre un exemple de commande à exécuter sur le nœud ODPS SQL :
-- project_name is the name of the MaxCompute project. use <project_name>; insert into table <project_name>.information_history select * from information_schema.tasks_history where ds ='datetime1';${datetime1}est un paramètre de planification DataWorks. À droite du nœud ODPS SQL, cliquez sur Scheduling Configuration. Dans la section Basic Properties, définissez le Parameter surdatetime1=${yyyymmdd}.RemarquePour analyser simultanément les métadonnées de plusieurs projets MaxCompute, créez plusieurs nœuds ODPS SQL. Configurez chaque nœud pour écrire les métadonnées d'un projet différent dans la même table de sauvegarde.
Étape 4 : Créer des jobs pour analyser les N premiers comptes de facturation et les jobs chronophages
Le champ settings de la vue TASKS_HISTORY enregistre les informations du planificateur ou de l'utilisateur au format JSON. Cela inclut useragent, bizid, skynet_id et skynet_nodename. Vous pouvez utiliser le champ settings pour trouver l'utilisateur RAM qui a créé le job. Cela vous permet d'utiliser la table de sauvegarde pour identifier les N premiers comptes de facturation et les jobs les plus chronophages. Voici les étapes à suivre :
-
Connectez-vous au client MaxCompute et créez une table de détails des utilisateurs RAM nommée user_ram. Cette table enregistrera les comptes et les ID de compte à analyser.
Le code suivant montre un exemple de commande :
CREATE TABLE if NOT EXISTS <project_name>.user_ram ( user_id STRING ,user_name STRING ); -
Créez une table de détails nommée cost_topn pour enregistrer les détails des N premiers comptes de facturation.
Le code suivant montre un exemple de commande :
CREATE TABLE if NOT EXISTS <project_name>.cost_topn ( cost_sum DECIMAL(38,5) ,task_owner STRING ) partitioned BY ( ds STRING ); -
Créez une table de détails nommée time_topn pour enregistrer les détails des N premiers jobs chronophages.
Le code suivant montre un exemple de commande :
CREATE TABLE if NOT EXISTS <project_name>.time_topn ( inst_id STRING ,cost_time BIGINT ,task_owner STRING ) partitioned BY ( ds STRING ); -
Accédez à l'interface Data Studio de DataWorks. Créez un nœud ODPS SQL (topn) et configurez la planification horaire pour écrire périodiquement les données statistiques de la table
cost_topndans la tableuser_ram. Cliquez ensuite sur l'icône
en haut à gauche pour enregistrer le nœud.Pour plus d'informations, consultez la section Créer un nœud ODPS SQL.
Le code suivant montre un exemple de commande à exécuter sur le nœud ODPS SQL :
-- Enable data type 2.0. For more information about data type 2.0, see Data type editions. SET odps.sql.decimal.odps2=true; -- Write metadata to the cost_topn and time_topn tables. user_id is the account ID. You can find the account ID on your personal information page. INSERT INTO TABLE <project_name>.cost_topn PARTITION (ds = '${datetime1}') SELECT NVL(cost_sum,0) cost_sum ,CASE WHEN a.task_owner='<user_id>' OR a.task_owner='<user_id>' OR a.task_owner='<user_id>' THEN b.user_name ELSE a.task_owner END task_owner FROM ( SELECT inst_id ,owner_name ,task_type ,a.input_bytes ,a.cost_cpu ,a.status ,CASE WHEN a.task_type = 'SQL' THEN CAST(a.input_bytes/1024/1024/1024 * a.complexity * 0.3 AS DECIMAL(18,5) ) WHEN a.task_type = 'SQLRT' THEN CAST(a.input_bytes/1024/1024/1024 * a.complexity * 0.3 AS DECIMAL(18,5) ) WHEN a.task_type = 'CUPID' AND a.status='Terminated' THEN CAST(a.cost_cpu/100/3600 * 0.66 AS DECIMAL(18,5) ) ELSE 0 END cost_sum ,a.settings ,GET_JSON_OBJECT(settings, "$.SKYNET_ONDUTY") owner ,CASE WHEN GET_JSON_OBJECT(a.settings, "$.SKYNET_ONDUTY") IS NULL THEN owner_name ELSE GET_JSON_OBJECT(a.settings, "$.SKYNET_ONDUTY") END task_owner FROM information_history WHERE ds = '${datetime1}' ) a LEFT JOIN <project_name>.user_ram b ON a.task_owner = b.user_id; INSERT INTO TABLE <project_name>.time_topn PARTITION(ds = '${datetime1}') SELECT inst_id ,cost_time ,CASE WHEN a.task_owner='<user_id>' OR a.task_owner='<user_id>' OR a.task_owner='<user_id>' THEN b.user_name ELSE a.task_owner END task_owner FROM ( SELECT inst_id ,task_type ,status ,DATEDIFF(a.end_time, a.start_time, 'ss') AS cost_time ,CASE WHEN GET_JSON_OBJECT(a.settings, "$.SKYNET_ONDUTY") IS NULL THEN owner_name ELSE GET_JSON_OBJECT(a.settings, "$.SKYNET_ONDUTY") END task_owner FROM <project_name>.information_history a WHERE ds = '${datetime1}' ) a LEFT JOIN <project_name>.user_ram b ON a.task_owner = b.user_id;RemarqueDans l'exemple,
task_type = 'SQL'représente un job SQL,task_type = 'SQLRT'représente un job d'accélération des requêtes ettask_type = 'CUPID'représente un job Spark. Pour analyser d'autres jobs facturables, tels que les jobs MapReduce ou Mars, ajoutez des lignes de code en fonction de leurs formules de facturation. Pour plus d'informations sur la facturation, consultez les sections Tarification du calcul (paiement à l'utilisation).${datetime1}est un paramètre de planification DataWorks. À droite du nœud ODPS SQL, cliquez sur Scheduling Configuration. Dans la section Basic Properties, définissez le Parameter surdatetime1=${yyyymmdd}.
Étape 5 : Créer un robot de chat de groupe DingTalk et envoyer des informations sur les N premiers comptes de facturation et les jobs chronophages
Les étapes suivantes montrent comment créer un robot de chat de groupe DingTalk et envoyer des informations sur les N premiers comptes de facturation et les jobs chronophages. Les étapes utilisent le client PC DingTalk comme exemple.
-
Créez un robot de chat de groupe DingTalk.
Sélectionnez le groupe DingTalk cible et cliquez sur l'icône
en haut à droite.Dans le panneau Group Settings, cliquez sur Smart Group Assistant.
Dans le panneau Smart Group Assistant, cliquez sur Add Robot.
Dans la section Add Robot de la boîte de dialogue Group Robot, cliquez sur l'icône
.Dans la boîte de dialogue Group Robot, cliquez sur Custom.
Dans la boîte de dialogue Robot Details, cliquez sur Add.
-
Dans la boîte de dialogue Add Robot, modifiez les informations du robot.
Nom de la propriété
Règles de configuration
Photo de profil
Cliquez sur l'icône
en bas à droite de la photo de profil pour la modifier.Nom du robot
Saisissez un nom pour le robot.
Paramètres de sécurité
Configurez les paramètres de sécurité requis (sélectionnez-en au moins un), cochez J'ai lu et j'accepte les « Conditions de service et clause de non-responsabilité relatives aux robots personnalisés », puis cliquez sur Terminer.
Il existe trois types de paramètres de sécurité :
Mots-clés personnalisés : vous pouvez définir jusqu'à 10 mots-clés.
Ajouter une signature : sélectionnez Ajouter une signature pour obtenir la clé du robot.
Adresse IP (plage) : seules les requêtes provenant de la plage d'adresses IP spécifiée sont traitées.
-
Dans la boîte de dialogue Add Robot, copiez l'URL Webhook générée. Cliquez ensuite sur Finish.
ImportantGardez l'URL Webhook sécurisée. Ne la publiez pas sur des sites web externes. Une URL divulguée peut entraîner des risques de sécurité.
-
Utilisez IntelliJ IDEA pour créer un projet Maven et compiler le programme Java qui envoie des messages au groupe DingTalk. Après la compilation, un package JAR est généré.
Pour plus d'informations sur l'utilisation d'IntelliJ IDEA, cliquez sur Help en haut à droite de l'interface IntelliJ IDEA.
-
Configurez les dépendances Pom.
Le code suivant montre les dépendances Pom.
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>DingTalk_Information</groupId> <artifactId>DingTalk_Information</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>com.aliyun.odps</groupId> <artifactId>odps-sdk-core</artifactId> <version>0.35.5-public</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.15</version> <exclusions> <exclusion> <groupId>com.sun.jmx</groupId> <artifactId>jmxri</artifactId> </exclusion> <exclusion> <groupId>com.sun.jdmk</groupId> <artifactId>jmxtools</artifactId> </exclusion> <exclusion> <groupId>javax.jms</groupId> <artifactId>jms</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>alibaba-dingtalk-service-sdk</artifactId> <version>1.0.1</version> </dependency> <dependency> <groupId>com.aliyun.odps</groupId> <artifactId>odps-jdbc</artifactId> <version>3.0.1</version> <classifier>jar-with-dependencies</classifier> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.4.1</version> <configuration> <!-- get all project dependencies --> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <!-- MainClass in mainfest make a executable jar --> <archive> <manifest> <mainClass>com.alibaba.sgri.message.test</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <!-- bind to the packaging phase --> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project> -
Développez le programme Java et générez le package JAR topn_new.jar.
Le code suivant montre un exemple Java :
package com.alibaba.sgri.message; import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; import com.aliyun.odps.Instance; import com.aliyun.odps.Odps; import com.aliyun.odps.OdpsException; import com.aliyun.odps.account.Account; import com.aliyun.odps.account.AliyunAccount; import com.aliyun.odps.data.ResultSet; import com.aliyun.odps.task.SQLTask; import com.dingtalk.api.DefaultDingTalkClient; import com.dingtalk.api.DingTalkClient; import com.dingtalk.api.request.OapiRobotSendRequest; import com.dingtalk.api.response.OapiRobotSendResponse; import com.taobao.api.ApiException; public class test { public static void main(String[] args) throws ApiException { if (args.length < 1) { System.out.println("Please enter the date parameter."); System.exit(0); } System.out.println("Start reading data."); DingTalkClient client = new DefaultDingTalkClient( "<Your chatbot's Webhook URL>"); OapiRobotSendRequest request = new OapiRobotSendRequest(); request.setMsgtype("markdown"); OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown(); // The date here is used as a parameter. markdown.setText(getContent(args[0])); markdown.setTitle("Top N jobs by consumption"); request.setMarkdown(markdown); OapiRobotSendResponse response = client.execute(request); System.out.println("Message sent successfully."); } /** * Read from ODPS to get the data to send. */ public static String getContent(String day) { Odps odps = createOdps(); StringBuilder sb = new StringBuilder(); try { //==================Billing accounts===================== String costTopnSql = "select sum(cost_sum)cost_sum,task_owner from cost_topn where ds='" + day + "' " + "group by task_owner order by cost_sum desc limit 5;"; Instance costInstance = SQLTask.run(odps, costTopnSql); costInstance.waitForSuccess(); ResultSet costTopnRecords = SQLTask.getResultSet(costInstance); sb.append("<font color=#FF0000 size=4>").append("Top N Billing Accounts (").append(day).append( ")[Calculated based on Alibaba Cloud pay-as-you-go billing]").append("</font>").append("\n\n"); AtomicInteger costIndex = new AtomicInteger(1); costTopnRecords.forEach(item -> { sb.append(costIndex.getAndIncrement()).append(".").append("Account:"); sb.append("<font color=#2E64FE>").append(item.getString("task_owner")).append("\n\n").append("</font>"); sb.append(" ").append(" ").append("Cost:").append("<font color=#2E64FE>").append(item.get("cost_sum")) .append(" CNY").append( "</font>").append("\n\n") .append("</font>"); }); //==================Time-consuming jobs===================== String timeTopnSql = "select * from time_topn where ds='" + day + "' ORDER BY cost_time DESC limit 5;"; Instance timeInstance = SQLTask.run(odps, timeTopnSql); timeInstance.waitForSuccess(); ResultSet timeTopnRecords = SQLTask.getResultSet(timeInstance); sb.append("<font color=#FF8C00 size=4>").append("Top N Time-consuming Jobs (").append(day).append(")") .append("\n\n").append("</font>"); AtomicInteger timeIndex = new AtomicInteger(1); timeTopnRecords.forEach(item -> { sb.append(timeIndex.getAndIncrement()).append(".").append("Job:"); sb.append("<font color=#2E64FE>").append(item.getString("inst_id")).append("\n\n").append("</font>"); sb.append(" ").append("Account:").append("<font color=#2E64FE>").append(item.getString("task_owner")).append("\n\n").append("</font>"); sb.append(" ").append("Duration:").append("<font color=#2E64FE>").append(item.get("cost_time")) .append("s").append( "</font>").append("\n\n"); }); } catch (OdpsException | IOException e) { e.printStackTrace(); } return sb.toString(); } /** * Create an ODPS object. */ public static Odps createOdps() { String project = "<project_name>"; // An Alibaba Cloud account AccessKey has permissions to access all APIs. This poses a high security risk. We strongly recommend that you create and use a RAM user to make API calls or perform O&M. To create a RAM user, log on to the RAM console. // This example shows how to store the AccessKey ID and AccessKey secret in environment variables. You can also store them in a configuration file as needed. // We strongly recommend that you do not hard-code the AccessKey ID and AccessKey secret in your code. This can lead to key leakage. String accessId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"); String accessKey = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"); String endPoint = "http://service.odps.aliyun.com/api"; Account account = new AliyunAccount(accessId, accessKey); Odps odps = new Odps(account); odps.setEndpoint(endPoint); odps.setDefaultProject(project); return odps; } } -
Téléchargez le package topn_new.jar généré en tant que ressource MaxCompute.
Pour plus d'informations, consultez la section Créer et utiliser des ressources MaxCompute.
-
-
Créez un nœud Shell nommé dingsend, référencez le package topn_new.jar et configurez une planification récurrente.
Pour plus d'informations, consultez la section Nœud Shell.
Le code suivant montre un exemple de commande à exécuter sur le nœud Shell :
java -jar topn_new.jar $1$1est un paramètre de planification DataWorks. À droite du nœud Shell, cliquez sur Scheduling Configuration. Dans la section Basic Properties, définissez le Parameter sur${yyyymmdd}.
Étape 6 : Configurer les propriétés de planification des nœuds parents et enfants et exécuter les nœuds
Dans le panneau de flux métier, connectez les nœuds information_history, topn et dingsend pour créer des dépendances. Configurez les propriétés de réexécution et les dépendances des nœuds parents pour chaque nœud. Une fois la configuration terminée, faites un clic droit sur un nœud et sélectionnez Run Node.
Pour plus d'informations sur la configuration des dépendances, consultez la section Configurer les dépendances de planification dans le même cycle.
Pour plus d'informations sur la configuration des nœuds parents et enfants, consultez la section Configurer le contexte du nœud.
Références
Support en ligne
Si vous avez des questions ou des suggestions lors de l'utilisation de MaxCompute, vous pouvez soumettre un ticket pour contacter le support technique.