Archivo del Autor: sbgermanm

#AOS2K15

CH-K8e4WwAAR0ws (2)

Los pasados 19 y 20 de Junio estuve de nuevo en la AOS. Esta vez se celebró en Gijón, una ciudad preciosa que no os voy a descubrir ahora.
No elegí el alojamiento oficial de la organización (camping de Deva) por problemas logísticos y me decanté por uno de los hoteles con los la organización nos ofrecía descuentos, el Hotel Asturias. Fue un gran acierto, el Hotel tiene una ubicación magnifica, impresionante, quería decirlo pero no me enrollo mas, vamos a lío.

Que es una AOS (Agile Open Space)
Un open space es un evento auto organizado por los asistentes a la misma. Básicamente: No hay agenda, la agenda se hace al inicio de cada día de AOS. Tampoco hay propuestas previas, las propuestas se presentan al inicio de cada día y se eligen por los asistentes. Si queréis una explicación mas profunda podéis verlo en la pagina de la organización

Si ya lo habéis leído, solo os comento una pequeña reflexión: De una AOS te llevarás lo que quieras llevar, depende de tí y para aprovechar una AOS, hay que ir con las pilas puestas, es un evento muy exigente y hacer de “mariposa” es mas que necesario para poder aguantar el ritmo (buscad “abeja, mariposa y open space”).

Porque mola una AOS
En una AOS lo más habitual es tener debates muy abiertos, con mucha libertad para participar, para aportar y poder recoger otros puntos de vista y experiencias. Aunque puede haber reuniones unidireccionales, la gran mayoría son mesas redondas.

Una de las cosas que más valoro es que recoges muchas experiencias de verdad, no de libro. Casos de uso de agile en entorno reales y duros como la vida misma. En otro tipo de reuniones suele haber mucha teoría y además, todo está muy preparado. El ponente prácticamente está pasando un examen sobre lo que cuenta, no te tienes que preocupar de ser “correcto”, solo de aportar y recoger todo lo posible.

Algunas reuniones a las que fui
SAFe
No quiero acercarme a los frameworks y métodos en general para escalar agile que están saliendo en los últimos años. Tengo mis razones para no hacerlo pero no podía dejar pasar la oportunidad de tener un debate al respecto y no me arrepentí. El debate estuvo genial, intenso, con gente que está en el día a día usando SAFe y que nos contó como lo están aplicando. Me lleve una primera impresión de las soluciones que SAFe intenta aplicar a los problemas que encuentras al querer escalar. Fue una de la reuniones más interesantes (para mí, claro).

AARRR + story mapping
Fui a la AOS en tren desde Madrid. Son 5 horas y media pero no me importa porque me encanta el tren. Además me da la oportunidad de ir viendo vídeos (previamente descargados, lo de la wifi es ciencia ficción) que tengo atrasados desde hace tiempo.

Henrik Kniberg at LKCE14

 

Precisamente uno de los que más me ha gustado últimamente es la keynote de Henrik Kniberg en la pasada ALE , sobre el “entregable” de cada spring, en el que hablaba, entre otras cosas, de las métricas pirata.

Por eso, en cuanto se planteó una charla sobre AARRR e story mapping no me lo pensé ni un momento, estaba muy arriba en mi lista.
La charla no me defraudo, una buena explicación de como complementar un story mapping con técnicas AARRR para darle valor (la medida del valor) a los elementos planificados.
Siempre hablamos de priorizar las historias a planificar en el spring por su valor (de negocio) pero, como se consigue saber esa valoración? Intuición? Inspiración divina? Lo fácil que sea o chulo que parezca? Encuestas a usuario? Esta charla me clarifico formas de encauzar esas decisiones.
#noprojects
#noproject es otra de las corrientes que hay por la comunidad, igual que #noestimates y otras. Que es un proyecto? Desde pequeños nos han enseñado que para hacer un proyecto necesitamos un alcance + un presupuesto (recurso) + un deadline. No sé de qué mágica forma cumplir con scope, budget y fecha asegura reportar un beneficio a nuestro cliente pero en cualquier caso la verdad es que esto cuadra muy mal con el desarrollo de software.

PMI define un proyecto como un esfuerzo encaminado a conseguir un objetivo en una fecha determinada. (Yo no creo que tenga un fin definido y lo del principio, podríamos discutir mucho cuando empieza un proyecto). Es necesario un alcance? No se puede conseguir el objetivo mejor con sucesivas entregas? Tiene fin un proyecto software? Mucho que discutir ahí, desde que un alcance no se conoce (caminante no hay camino…) hasta que el único proyecto sin cambios es un proyecto que no se usa por nadie.

Equipos desorganizados
Otra de las charlas que me impactó fue la relacionada con equipos desorganizados . Realmente debe haber un “equipo”? Es el equipo la forma ideal de trabajar? Es lógico que los proyectos te “toquen”? No es más lógico que tú elijas a que proyectos te apuntas? Y es más, con qué nivel de compromiso te apuntas, no siempre tienes la misma disposición, somos personas con vida en el trabajo y fuera de él, con altibajos no deseados y altibajos deseados. No es más lógico una forma de trabajo estilo freelance?. Mucho en lo que pensar porque la verdad es que la uniformización en la forma de trabajar puede dar una imagen de orden y eficiencia pero no es natural que todos hagamos las cosas de la misma forma todo el tiempo….
Una parte muy positiva que me llevo de la charla es cuestionarlo todo, cuestionar en que nos basamos para pensar que hay que hacer las cosas como las hacemos. La charla fue genial, muy abierta y con muchas opiniones.

Fracaso Agile
En esta reunión me lleve uno de los problemas que cada vez más común, en el afán de ser agiles, estamos adoptando las técnicas pero no los principios y valores.

Agile Chasm

http://cmforagile.blogspot.com.es/2015/04/have-you-crossed-agile-chasm.html

Se está vaciando de contenido. Estamos cayendo por el precipicio? Me recuerda a algo que ocurre mucho con las matemáticas, cuando ante un problema el niño al que estas intentando enseñar a pensar cómo resolver te pregunta “pero, es de sumar o de restar”. Aplicando solo el método de resolución no vamos a saber resolver el problema.

Otras que no pude ir
PopcornFlow
Una de las que no pude asistir fue una charla sobre una experiencia usando PopcornFlow. Cosa de la AOS y de no poder estar en varios sitios a la vez. Da la casualidad que en el tren venia viendo un vídeo de Claudio Perrone sobre A3 Thinking y PopcornFlow y llegue a Gijón justo antes de empezar con PopcornFlow, con lo que no sabía de qué iba.

Evolve or die_ A3 thinking and popcorn flow in action – Claudio Perrone at LKCE1

En el viaje de vuelta terminé el vídeo y la verdad es que tiene una pinta fantástica y queda anotado en mi backlog buscar experiencias usándolo.

#NoEstimates
Otra a la que no pude ir… Esta tengo muy clara la “teoría” y estoy totalmente de acuerdo con la filosofía que hay tras ello, pero quiero recoger como se usa en proyectos de verdad… Al backlog…

 

Equipo AOS
Desde aquí quiero trasmitir mi enorme agradecimiento al equipo organizador de la AOS. Cuando piensas en la cantidad de curro y de ilusión que hay que echar para organizar algo como esto, alucinas. Muchas gracias por vuestro esfuerzo y dedicación, nos hicisteis disfrutar de una AOS genial.
equipo aos

Disclaimer
Este articulo no pretende ser una valoración y ni siquiera una descripción de las charlas que hubo, el contenido fue mucho mas amplio y las discusiones mucho mas ricas de lo que soy capaz de poner y además, sobre la AOS hay tantas conclusiones como personas asistieron, cada cual se he llevado la suya. Solo representa una parte de lo que yo me he llevado.

Ah tambien me he llevado esta foto:

IMG_20150618_143153

Youtube API – How to copy the WatchLater List

Disclaimer

All the code here has been tested for 5 or 10 minutes… Use at your own risk. This is intended to be only a draft, a demo of the Youtube API possibilities and it is offered without any warranty.

 

OMG, It is written in English…

This post is going to be written in English. I must practice my English and write this will be a good way. So let it go…

 

Why do you want to copy the Watch Later List?

(don’t read this, there is no code here, continue below)  

When I code for pleasure, out of the office, at home or sometimes, on a hotel room, I have a particular way to do it. Some people likes to hear classical music, some prefer video games BSOs, some others totally silence… I like to see youtube music videos. Actually, most of the time, I don’t look at them, I only hear them but I like the way I can made a music selection on youtube. Let’s me explain it…

Before I begin to code, I do a selection of videos. The easy way of doing a selection is to add then to the “watch later” playlist. The selection last for a few days and I made a new one, normally because I want to hear a different kind of music (You know, sometime you prefer POP, sometimes Rock, sometimes games BSO…). But I don’t want to lose the old selection so I need to save it.

In the past you can do it on YouTube, you can re-organize your watch later list and copy selected videos to other list. But this is not more possible.
Last saturday evening I was very upset for this little problem so I google a little until find the youtube info API. And this article is the result. Now I can do that and a few things more…

 

How to do it

(if you don’t want to read more, you would prefer go to the github repository directly: https://github.com/sbgermanm/youtubeV2)

1. We need a google api client ID

1.1 Go to google api console: https://console.developers.google.com/

1.2 Create a new project

Crear proyecto

1.3 Activate youtube data api

enable api2

1.4 Create new client ID. Here you can take the data for the file client_secrets.json

create client id

client id created
1.5 Fill in the consent screen

consent screen
1.6 You are done

 

Let’s do it

Now that you can use the youtube api, let’s go make an application:

2. Resources

To understand how the API works, there are three importants helps from google:
2.1 The introduction to how the API works: https://developers.google.com/youtube/v3/getting-started
2.2 The API reference: https://developers.google.com/youtube/v3/docs/, where you can see the methods, the resource json structure (to figure out where you can get the data), the diferents resouce propoerties and some samples.
2.3 The API explorer: https://developers.google.com/apis-explorer/#p/youtube/v3/ a very useful resource to try the API. Here you can use all the api, try with different parameters and see the json request and response. It’s very important to know that you can limit the response of the api on several ways. You can read it in the first resource and you can interactively try it in this resource to make sure that you get what you want and only that. For example, you can easily compose the “field” parameter of the API.

3. The Code

As a line of code is better than 1 hundred words of comments, let’s code:

3.1 The pom.xml

<?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>es.sebas</groupId>
    <artifactId>youtube2</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>jar</packaging>

    <repositories>
        <repository>
            <id>google-api-services</id>
            <url>http://google-api-client-libraries.appspot.com/mavenrepo</url>
        </repository>
    </repositories>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.youtube.version>v3-rev91-1.17.0-rc</project.youtube.version>
        <project.http.version>1.19.0</project.http.version>
        <project.oauth.version>1.19.0</project.oauth.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    </properties>
    <dependencies>

        <!-- YouTube Data V3 support -->
        <dependency>
            <groupId>com.google.apis</groupId>
            <artifactId>google-api-services-youtube</artifactId>
            <version>${project.youtube.version}</version>
        </dependency>

        <dependency>
            <groupId>com.google.http-client</groupId>
            <artifactId>google-http-client-jackson2</artifactId>
            <version>${project.http.version}</version>
        </dependency>

        <dependency>
            <groupId>com.google.oauth-client</groupId>
            <artifactId>google-oauth-client-jetty</artifactId>
            <version>${project.oauth.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Forces Maven to use Java 1.6 -->
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArgument></compilerArgument>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <name>youtube2</name>
</project>

 

3.2 The methods used in this function
3.2.1 Authorize

public static Credential authorize() throws IOException {

        List<String> scopes = Arrays.asList("https://www.googleapis.com/auth/youtube");

        Reader reader = new InputStreamReader(PlayListTools.class.getResourceAsStream("/client_secrets.json"));
        // Load client secrets.
        GoogleClientSecrets clientSecrets
                = GoogleClientSecrets.load(
                        JSON_FACTORY,
                        reader);

        FileDataStoreFactory fileDataStoreFactory = new FileDataStoreFactory(new File(System.getProperty("user.home") + "/" + CREDENTIALS_DIRECTORY));
        DataStore<StoredCredential> datastore = fileDataStoreFactory.getDataStore("youtubesebas");

        // Set up authorization code flow.
        GoogleAuthorizationCodeFlow flow
                = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT,
                        JSON_FACTORY,
                        clientSecrets,
                        scopes)
                .setCredentialDataStore(datastore)
                .build();

        // Build the local server and bind it to port 9000
        LocalServerReceiver localReceiver = new LocalServerReceiver.Builder().setPort(8080).build();

        // Authorize.
        return new AuthorizationCodeInstalledApp(flow, localReceiver).authorize("user");
}

and the credentials for the authorization client_secrets.json (put here the data you get on section 1.4)

{
 "installed": {
 "client_id": "Enter your client id here",
 "client_secret": "Enter your client secret here"
 }
}

 

3.2.2 Recover all watch later items

public static List<PlaylistItem> getAllWatchLaterItems(Credential credential) {

        String wlPlaylistId = getWlID(credential);
        System.out.println("WatchLaterId : " + wlPlaylistId);
        return getAllPlayListItems(credential, wlPlaylistId);
}

public static List<PlaylistItem> getAllPlayListItems(Credential credential, String playListID) {
        // List to store all PlaylistItem items associated with the uploadPlaylistId.
        ArrayList<PlaylistItem> playlistItemList = new ArrayList<PlaylistItem>();

        /*
         * Now that the user is authenticated, the app makes a channel list request to get the
         * authenticated user's channel. Returned with that data is the playlist id for the uploaded
         * videos. https://developers.google.com/youtube/v3/docs/channels/list
         */
        YouTube youtube = new YouTube.Builder(new NetHttpTransport(), new JacksonFactory(), credential)
                .setApplicationName("youtube-sebas")
                .build();

        /*
         * Now that we have the playlist id for your uploads, we will request the playlistItems
         * associated with that playlist id, so we can get information on each video uploaded. This
         * is the template for the list call. We call it multiple times in the do while loop below
         * (only changing the nextToken to get all the videos).
         * https://developers.google.com/youtube/v3/docs/playlistitems/list
         */
        YouTube.PlaylistItems.List playlistItemRequest;
        try {
            playlistItemRequest = youtube.playlistItems().list("id,contentDetails,snippet");
            playlistItemRequest.setPlaylistId(playListID);

            // This limits the results to only the data we need and makes things more efficient.
            playlistItemRequest.setFields(
                    "items(id,contentDetails/videoId,snippet/title),nextPageToken,pageInfo");

            String nextToken = "";

            // Loops over all search page results returned for the uploadPlaylistId.
            do {
                playlistItemRequest.setPageToken(nextToken);
                PlaylistItemListResponse playlistItemResult = playlistItemRequest.execute();

                playlistItemList.addAll(playlistItemResult.getItems());

                nextToken = playlistItemResult.getNextPageToken();
            } while (nextToken != null);

        } catch (IOException ex) {
            Logger.getLogger(PlayListTools.class.getName()).log(Level.SEVERE, null, ex);
        }

        return playlistItemList;
}

 

3.2.3 Insert a new playList

public static String insertPlaylist(String playlistTitle, String playlistDesc, Credential credential) throws IOException {

        /*
         * We need to first create the parts of the Playlist before the playlist itself.  Here we are
         * creating the PlaylistSnippet and adding the required data.
         */
        PlaylistSnippet playlistSnippet = new PlaylistSnippet();
        playlistSnippet.setTitle(playlistTitle);
        playlistSnippet.setDescription(playlistDesc);

        // Here we set the privacy status (required).
        PlaylistStatus playlistStatus = new PlaylistStatus();
        playlistStatus.setPrivacyStatus("private");

        /*
         * Now that we have all the required objects, we can create the Playlist itself and assign the
         * snippet and status objects from above.
         */
        Playlist youTubePlaylist = new Playlist();
        youTubePlaylist.setSnippet(playlistSnippet);
        youTubePlaylist.setStatus(playlistStatus);

        /*
         * This is the object that will actually do the insert request and return the result.  The
         * first argument tells the API what to return when a successful insert has been executed.  In
         * this case, we want the snippet and contentDetails info.  The second argument is the playlist
         * we wish to insert.
         */
        // YouTube object used to make all API requests.
        YouTube youtube = new YouTube.Builder(new NetHttpTransport(), new JacksonFactory(), credential)
                .setApplicationName("youtube-sebas")
                .build();

        YouTube.Playlists.Insert playlistInsertCommand
                = youtube.playlists().insert("snippet,status", youTubePlaylist);
        Playlist playlistInserted = playlistInsertCommand.execute();

        // Pretty print results.
        System.out.println("New Playlist name: " + playlistInserted.getSnippet().getTitle());
        System.out.println(" - Privacy: " + playlistInserted.getStatus().getPrivacyStatus());
        System.out.println(" - Description: " + playlistInserted.getSnippet().getDescription());
        System.out.println(" - Channel: " + playlistInserted.getSnippet().getChannelId() + "n");
        return playlistInserted.getId();

}

 

3.2.4 Insert the previously recovered items (the watch later items)

public static void insertPlaylistItems(Credential credential, String playlistId, List<PlaylistItem> playListItems) {

        for (PlaylistItem playlistItem : playListItems) {
            try {
                System.out.println("Inserting Video, ID=" + playlistItem.getContentDetails().getVideoId() + " with title: " + playlistItem.getSnippet().getTitle());
                insertPlaylistItem(credential, playlistId, playlistItem.getContentDetails().getVideoId(), playlistItem.getSnippet().getTitle());
            } catch (IOException ex) {
                Logger.getLogger(PlayListTools.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

}

private static String insertPlaylistItem(Credential credential, String playlistId, String videoId, String title) throws IOException {

        /*
         * The Resource type (video,playlist,channel) needs to be set along with the resource id. In
         * this case, we are setting the resource to a video id, since that makes sense for this
         * playlist.
         */
        ResourceId resourceId = new ResourceId();
        resourceId.setKind(RESOURCE_KIND_VIDEO);
        resourceId.setVideoId(videoId);

        /*
         * Here we set all the information required for the snippet section.  We also assign the
         * resource id from above to the snippet object.
         */
        PlaylistItemSnippet playlistItemSnippet = new PlaylistItemSnippet();
        playlistItemSnippet.setTitle(title);
        playlistItemSnippet.setPlaylistId(playlistId);
        playlistItemSnippet.setResourceId(resourceId);

        /*
         * Now that we have all the required objects, we can create the PlaylistItem itself and assign
         * the snippet object from above.
         */
        PlaylistItem playlistItem = new PlaylistItem();
        playlistItem.setSnippet(playlistItemSnippet);

        /*
         * This is the object that will actually do the insert request and return the result.  The
         * first argument tells the API what to return when a successful insert has been executed.  In
         * this case, we want the snippet and contentDetails info.  The second argument is the
         * playlistitem we wish to insert.
         */
        YouTube youtube = new YouTube.Builder(new NetHttpTransport(), new JacksonFactory(), credential)
                .setApplicationName("youtube-sebas")
                .build();
        YouTube.PlaylistItems.Insert playlistItemsInsertCommand
                = youtube.playlistItems().insert("snippet,contentDetails", playlistItem);
        PlaylistItem returnedPlaylistItem = playlistItemsInsertCommand.execute();

        printPlayListItem(returnedPlaylistItem);

        return returnedPlaylistItem.getId();

}

 

3.2.5 Some globals…

 /**
 * Global instance of the HTTP transport.
 */
 private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();

 /**
 * Global instance of the JSON factory.
 */
 private static final JsonFactory JSON_FACTORY = new JacksonFactory();

/**
* Some constants...
*/
 private static final String RESOURCE_KIND_VIDEO = "youtube#video";
 private static final String CREDENTIALS_DIRECTORY = ".oauth-credentials";

 

3.2.6 The method that do the copy

public static void main(String[] args) {

        // Authorization.
        Credential credential = null;
        try {
            credential = PlayListTools.authorize();
        } catch (IOException ex) {
            Logger.getLogger(WacthLaterCopy.class.getName()).log(Level.SEVERE, null, ex);
        }

        List<PlaylistItem> wlPlayListItems = PlayListTools.getAllWatchLaterItems(credential);

        String playlistTitle = "Temporal Playlist " + Calendar.getInstance().getTime();
        String playlistDesc = "A private temporal playlist created with the YouTube API v3";
        String playlistId;
        try {
            playlistId = PlayListTools.insertPlaylist(playlistTitle, playlistDesc, credential);

            // If a valid playlist was created, adds a new playlistitem with a video to that playlist.
            PlayListTools.insertPlaylistItems(credential, playlistId, wlPlayListItems);
        } catch (IOException ex) {
            Logger.getLogger(WacthLaterCopy.class.getName()).log(Level.SEVERE, null, ex);
        }
}

 

3.2.7 The maven comand line to automate this

mvn exec:java -Dexec.mainClass=”es.sebas.youtube.WatChLaterCopy”

 

To be continued

Now we have the copy of the Watch Later List. In next post I will show :

  • How to Purge the Watch Later List
  • How to create a VideoLan List of the videos in our playLists

Write you later…

Calculo del coste de la licencia de Oracle Database – Sprint2

Continuamos…

Vamos con los cálculos

Para los ejemplos que vamos a usar, vamos a suponer que, por funcionalidad, nos vale cualquiera de las ediciones de BBDD (si no es así, tendríamos que usar como mínimo, la que cumpla nuestras condiciones)

Vamos a usar siempre la más barata.

Además considerare siempre que se compra la licencia perpetua, pero los cálculos cambiado los precios, son los mismos para la licencia anual.

Hay que tener en cuenta que se pagan dos cosas. Primero la licencia de uso, que se puede comprar anual o perpetua y segundo el soporte.

Vamos a suponer 3 hardwares diferentes.

Maquina1: 2 sockets con 1 CPUs instalada de 10 cores y 3 usuarios nominales
Maquina2: 4 sockets con 2 CPUs instaladas de 10 cores y 10 usuarios nominales
Maquina3: 8 Sockets con 6 CPUs de 10 cores y 90 usuarios nominales

Paso 1, Saber que edición de la BBDD necesitamos.

Para determinar la edición, tenemos que conocer la aplicación que queremos realizar y revisar las características de las edición de la BBDD en el enlace de más arriba. Un detalle, la SE1 y la SE son idénticas salvo si queremos usar RAC.

Paso 2. Conocer el hardware en el que correrá nuestra aplicación.

Y no quiero risas (como dice un amigo mío). Esto muchas veces no lo sabemos hasta el final, hasta que hacemos pruebas de rendimiento… Realmente no es crítico (para nuestros calculos). De hecho, como dije en el inicio del anterior Sprint, es posible que intentes modificar tu hardware cuando calcules el coste de las licencias…

Lo realmente crítico es el paso anterior. Es decir, si determinamos que las características de la SE1 son suficientes, podemos usar una SE1. Si al final estamos obligados a usar una SE o una EE, no habrá problemas porque son totalmente compatibles. De hecho, la instalación solo da a elegir entre EE y SE. Si vamos a licenciar SE1, tendremos que instalar SE. Luego se licencia una SE1 o una SE en función del hardware usado.

Paso 3. Aplicar los límites por el hardware.

Los límites se establecen en función del número de sockets que tenga nuestra maquina, estén ocupados todos o no lo estén:

  • SE1 permite un máximo 2 sockets
  • SE permite un máximo 4 sockets
  • EE sin límite

Así, para la Maquina1 podremos usar una SE1, para la Maquina2, la mínima es una SE y para la Maquina3 solo vale la EE.

Paso 4. Calcular el número de “unidades de facturación” a usar.

Estas “unidades de facturación” no aparece en ningún sitio con ese nombre pero este número es necesario para los cálculos del importe a pagar por licencias. Oracle, para las licencias, lo llama “processors”, pero esa palabra tiene otros significados. Lo voy a llamr UFO (Unidentified Facturation Object) (una vez más, no quiero risas aquí).

Este cálculo de UFOs se hace un función del número de cores o de CPUs que tenga instaladas nuestra maquina (aquí si, instalados, se limita por sockets pero se paga por CPUs).

Los UFOs, además, son necesarios tanto para la licencia por usuario como por procesador.
El número de UFOs para un mismo hardware dependiente de la edición de la BBDD a usar:

  • SE y SE1

Es necesario 1 UFO por cada CPU, independiente del número de cores que tengan nuestras CPUs

  • EE

El número de UFOs es numCPUs X numCores X Factor

El Factor depende del tipo de procesador, para Intel es 0,5.

Veamos los ejemplos

Maquina1
Serian 1 UFOs de SE1 (el número de CPUs)

Maquina2
Serian 2 UFOs de SE (el número de CPUs)

Maquina3
Serian 30 UFOs de EE: 6 CPUS * 10 * 0,5

Ojo, luego veremos que un UFO de SE no cuesta lo mismo que un UFO de EE, el de EE es 3 veces el de la SE y la SE es 3 veces el de la SE1

Paso 5. Calculo x procesador

Para el cálculo por procesador, simplemente hay que coger el número de UFOs anterior y multiplicarlo por el precio “Processor License” de la edición que corresponda. Podéis verlos en la lista publica de precios de Oracle (está en dólares).

Ejemplos

Maquina1, SE1

Licencia perpetua: 1×5.800€
Soporte 1 año: 1×1.276€

Maquina2, SE

Licencia perpetua: 2×17.500€
Soporte 1 año: 2×3.850€

Maquina3, EE

Licencia perpetua: 30×47.500€
Soporte 1 año: 30×10.450€

Paso 6. Calculo x Usuarios

Para el cálculo por número de usuarios, hay que multiplicar los usuarios x el precio por usuario (lógico, verdad?).

Hay que tener en cuenta el mínimo de usuarios, no se puede comprar menos que el mínimo marcado. Este mínimo depende de la edición y debe ser multiplicado por los UFOs.

Vamos a suponer que con el mínimo de usuarios nos basta, así que, vamos a calcular el mínimo a pagar. Como he puesto antes, podeís ver los precios en la lista publica de precios de Oracle (está en dólares).

Ejemplos del coste mínimo

Maquina1, SE1, mínimo 5 usuarios en la SE1

Licencia: 5 usuarios * 1 UFO * 180€
Soporte 1 año: 5 usuarios * 1 UFO * 39,60 €

Maquina2, SE, mínimo 5 usuarios en la SE, con 2 UF0s, el mínimo es 5 x 2

Licencia: 5 usuarios * 2 UFOs * 350€
Soporte 1 año: 5 usuarios * 2 UFOs * 77 €

Maquina3, EE, mínimo 25 usuarios en la EE, con 30 UFOs, el mínimo a comprar es 25 x 30

Licencia: 25 usuarios * 30 UFOs * 950€
Soporte 1 año: 25 usuarios * 30 UFOs * 209 €

Paso 7. ¿Cuando elegir Licencia x usuario o Licencia por procesador?

Esto es un cálculo muy simple y solo hay que mirar lo precios.

Maquina 1, SE1, 1 CPU

En la edición SE1, una licencia de procesador = 32,2 usuarios, con lo que, con menos de de 33 usuarios, compensa usar una licencia de tipo usuario, teniendo en cuenta que el mínimo de usuarios a comprar es 5.

Maquina 2, SE, 2 CPU

En este caso, una licencia de procesador = 50 usuarios, como tenemos que comprar 2 licencias de procesador, será más barato comprar por usuario hasta 100 usuarios, teniendo en cuenta que el mínimo de usuarios a comprar es 2*5, es decir, 10

Maquina 3, EE, 6 CPU x 10 cores

En este caso, una licencia de procesador también es = 50 usuarios, como tenemos que comprar 30 licencias de tipo procesador, será más barato comprar por usuario hasta 1500 usuarios teniendo en cuenta que el mínimo de usuarios a comprar es 30*25, es decir, 750

Conclusión

Como podemos ver, la elección de la edición tiene un coste muy elevado. Esto lleva incluso a plantearse el hardware a usar en función de los limites de licenciamiento de Oracle.

Por ejemplo, la maquina3 tiene 6 CPUs y 8 Sockets y el coste de 1er año de Oracle es casi un millón y medio de licencia (que se paga una sola vez) más 313 mil euros cada año.

Si las características de la SE son suficientes, os aseguro que yo haría pruebas de performance con una maquina con 4 CPUs únicamente.

Así, si limitamos a 4 CPUs (en una maquina de 4 Sockets) y la SE es suficiente, el coste pasa a ser de 70 mil euros de licencia + unos 15 mil de soporte anualmente.

Vosotros mismos, pero con esa pasta, contrato a un gurú de tunning y de paso, formo a mis desarrolladores en high performance applications…

Todo condicionado a que las características de la SE sean suficientes, por supuesto.

No he incluido aquí el dato por usuarios, porque lógicamente necesitas saber cuantos tienes, pero el mínimo de usuarios a comprar en este ejemplo, como sabrás por los cálculos anteriores, es de 750, con lo que el mínimo a pagar si tienes menos de 750 usuarios será justo la mitad de lo expuesto.

Posdata

Venga va, alguna cosa mas…

Cambio de plataforma

¿Que pasa si tengo licencias de BBDD en SUN Solaris y quiero pasar a X86 Linux?

Este es un tema que siempre me ha causado grandes dudas. De hecho, no tengo link de Oracle donde puedas contrastar esto.

Mi conocimiento sobre este detalle concreto es mas de “campo”. Si tienes una licencia de la BBDD para un sistema SPARC/Solaris, es gratis que pases esa licencia a un sistema X86/Red Hat Enterprise Linux (RHEL).

Entendiendo por licencia lo que has pagado, claro. Es decir, si tienes una maquina SUN con una CPU y has pagado una licencia de la edición standard para una CPU, eso es lo que tienes. Si tu nuevo sistema tiene 2 CPUs, evidentemente, tendrás que comprar otra licencia para la segunda CPU.

Actualizar la versión de la Base de Datos

A día de hoy, la Base de Datos va por su versión 12c, pero existen muchas instalaciones con la 10g, y la con la 9i. Pagar el soporte de Oracle da derecho a actualizar gratuitamente de versión.

Es decir, si has pagado una licencia de Oracle 9i y estás pagando el soporte, puedes actualizar hasta la 11g R2 sin coste adicional.

Certificación de la BBDD en tu plataforma

Lo primero que tienes que saber es si la versión de la BBDD está certificada en tu sistema operativo. Por ejemplo, la 11g ha sido certificada recientemente para su uso en Red Hat Enterprise Linux 6.1. Que sirva de ejemplo la siguiente tabla de compatibilidad con RHEL:

VERSIÓN PRODUCTO Documento Oracle
9.2.0 RHEL4 x86-64 353529.1
10.2.0 RHEL5 x86-64 421308.1
RHEL4 x86-64 339510.1
11.2.0 RHEL6 x86-64 1441282.1
RHEL5 x86-64 880989.1
RHEL4 x86-64 880942.1

Por último, el RAC, ese curioso elemento objeto de licenciamiento de Oracle

No sé qué concienzudos estudios de mercado han hecho en Oracle pero el tema de RAC es muy curioso.

El RAC (con limitaciones, como solo estar permitido el clusterware de Oracle) es gratis en la SE.

Solo puede usarse en la SE si la suma de todos los Sockets de todas las maquinas implicadas no supera en número a 4. Por ejemplo, se puede usar en 2 maquinas de 2 Sockets cada una.

Si usamos una edición EE, es una opción de pago adicional, que además hay que pagar en cada máquina que lo use. Es decir, si poner 4 maquinas, deberemos sumar todos sus UFOs y pagar una licencia tipo EE y una licencia de RAC por cada uno de los UFOs.

Ahora si:

FIN

Cálculo del coste de la licencia de Oracle Database – Sprint1

Disclaimer

Este no es un articulo vacuo y de “titulares”, por aquí no tenemos de esos, si queréis uno de esos os puedo pasar unas cuantas direcciones, así que, si vas a empezar a leerlo, piénsalo dos veces.

Introducción

En este articulo voy a intentar dar algo de luz sobre un tema recurrente: ¿cuánto cuesta la licencias de Oracle BBDD que necesito?

Uno esperaría encontrar estos datos de forma fácil y rápida pero Oracle se esfuerza denodadamente en que esto no sea así.

Supongo que es como esas tiendas pequeñas, que no te permiten mirar las cosas tranquilamente, en las que nada más entrar, se te tira encima el dependiente para “ayudarte”.

En Oracle deben preferir enviar la comercial a “ayudarte”. Por esto mismo, que este articulo sirva como guía, espero que te descubra algunos temas oculto, pero la última palabra la tiene siempre Oracle.

Después de pegarme con algunos de los “detalles” a tener en cuenta, y aún con la duda de la letra pequeña que mi miopía no me haya permitido alcanzar a leer, vamos con lo que he sacado en limpio.

Descubrirás como Oracle te puede hacer cambiar tu maquina de producción.

Si me preguntas a mí, desarrollador, que hardware es necesario poner en producción para poner online una calculadora, mi respuesta será siempre la misma: “la más gorda, es más barato el hardware que el precio las horas que gaste yo tuneándola”.

Pero, ¿qué pasa si esa calculadora guarda los datos en una BBDD Oracle? La película cambia…

A tener en cuenta

  • Los ejemplos concretos que pongan tendrá relación con x86 y Red Hat Enterprise Linux (RHEL), ya que es la plataforma con la que estoy más familiarizado pero las bases de estudio son extrapolables a otros sistemas
  • Solo vamos a hablar de las ediciones SE, SE1 y EE, por ser las típicas en aplicaciones empresariales
  • En todo momento vamos a dar por hecho que cualquiera de las ediciones de la BBDD de Oracle nos sirve para nuestros propósitos y eso es algo que tenéis que analizar

Conceptos

Vamos a empezar aclarando una serie de conceptos para no perdernos a lo largo del artículo.

Versión de la BBDD

Es lo que todos entendemos por versión. Ahora mismo la última versión es la 12.

Además del número de versión, Oracle añade una letra. Por ejemplo, las últimas versiones son 12c, 11g, 10g, 9i, 8i, etc.

Cada versión tiene una única letra para todas las releases de esa versión

La c es de Cloud, la g de Grid, y la i de Internet

Luego estan las releases, que añaden una R y un número de release ejemplo, 11g R2.

El número de versión completo es algo como 12.1.0.0.1 y la explicación de cada digito la tenéis aquí: Getting Started with Database Administration

Edición de la BBDD

Hay 5 ediciones de BBDD

    1. Oracle Database Standard Edition One (SE1).
    2. Oracle Database Standard Edition (SE)
    3. Oracle Database Enterprise Edition (EE)
    4. Oracle Database Express Edition (XE) .
    5. Oracle Database Personal Edition (PE)

Si quieres ver las diferencias entre las ediciones, puede ver los detalles en “Oracle Database Editions“.

Limitaciones de uso de las diferentes ediciones.

Oracle imponen dos tipos de limitaciones

  • Hardware permitido

La SE1 solo esta licenciada para que sea ejecutada en maquinas con un máximo de 2 sockets, por ejemplo

  • Funcionalidad

Oracle limita tanto la funcionalidad incluida, por ejemplo, Query Results Cache, como las opciones (de pago) que te permite usar, por ejemplo Oracle Spatial.

Pero para conocer cómo te afecta tendríamos que hablar de la aplicación que va a usar la BBDD, de tus requisitos no funcionales y de qué significa cada opción de la BBDD y todo eso no será hoy.

Sockets, CPUs y Cores

Socket es el espacio físico para “pinchar CPUs”.

CPU es el chip como tal, que puede incluir varios cores. Un sistema típico incluirá varias CPUs y cada una de estas varios cores. Por ejemplo, la CPU E7-8870 tiene 10 cores.

Tipos de licencias

Named user plus

Se paga por cada usuario que use el sistema.

Los usuarios son nominales, es decir, no son “usuarios concurrentes”, si no que la licencia se otorga a una persona con nombres y apellidos.

Permite que sea traspasada a otra pero para ello hay que hablar con Oracle

Los sistemas que accedan a la BBDD se consideran usuario también.

Además, hay un mínimo de usuarios a licenciar, dependiente de la BBDD, es decir, no se puede comprar una licencia para 2 usuarios de tipo Standard One, el mínimo son 5 en la SE1.

Processor

En esta modalidad se paga por el número de procesadores instalados y permite un número ilimitado de usuarios.

La licencia puede ser anual, pagando por cada año que se quiera disponer del producto, o perpetua, que da derecho a usarlo de por vida.

Soporte y actualización

El soporte es siempre anual, y es el 22% del importe de la licencia perpetua.

Da derecho a lo que todos conocemos por soporte y a la actualización a cualquier versión de la BBDD.

Hasta aquí ha llegado el primer Sprint, esto promete, permaneced atentos…