{"id":1582,"date":"2017-10-02T22:07:36","date_gmt":"2017-10-02T22:07:36","guid":{"rendered":"http:\/\/nenadnoveljic.com\/blog\/?p=1582"},"modified":"2017-10-02T22:07:36","modified_gmt":"2017-10-02T22:07:36","slug":"checkpoint-analytics","status":"publish","type":"post","link":"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/","title":{"rendered":"Checkpoint Analytics"},"content":{"rendered":"<h1>Log Switch Checkpoint<\/h1>\n<p>During log switch checkpoints, dirty blocks are being written to disk. It is important to keep in mind, that a redo log cannot be reused until its checkpoint has finished. Therefore, multiple uncompleted checkpoints could prevent further log switches, which in turn would cause write operations to wait until the redo logs can be reused again.<\/p>\n<p>Because the duration of checkpoints is so important, I&#8217;ve developed a couple of SQLs to analyze checkpoint patterns which might be helpful for identifying IO performance bottlenecks or properly sizing redo logs.<\/p>\n<h1>Alert Log<\/h1>\n<p>The timestamps of the beginning and the completion of individual checkpoints are being recorded in the alert log if the parameter <em>log_checkpoints_to_alert<\/em> is set to <em>TRUE<\/em>. This parameter is set to <em>FALSE<\/em> by default, so you&#8217;d need to enable the checkpoint information gathering first.<\/p>\n<p>The content of the alert log can be queried with the view <em>V$DIAG_ALERT_EXT<\/em> which accesses the alert log file as an external table. As doing more complex queries on an external table wouldn&#8217;t perform well, I&#8217;m going to load data into a table first:<\/p>\n<pre><code>create table checkpoint_events (\r\n    db varchar2(9 byte) not null ,  \r\n    originating_timestamp timestamp(9)  not null, \r\n    event varchar2(9) not null, scn integer not null \r\n) ;\r\n\r\ninsert into checkpoint_events   \r\n  SELECT \r\n    regexp_replace(adr_home,'.*\/(.*)','\\1'),\r\n    originating_timestamp,\r\n    regexp_substr(message_text,'Beginning|Completed'),\r\n    replace( \r\n        regexp_replace(message_text,'.*SCN: ([[:digit:]])','\\1') , chr(10),''\r\n    )\r\n  from V$DIAG_ALERT_EXT\r\n  where\r\n    (\r\n      message_text like 'Beginning%checkpoint%' or  \r\n      message_text like 'Completed%checkpoint%'\r\n    ) \r\n;\r\n\r\ncommit ;\r\n<\/code><\/pre>\n<p>In addition to loading data, the commands above do the following:<\/p>\n<ul>\n<li>extract checkpoint SCNs from the message text,<\/li>\n<li>discard non-relevant information,<\/li>\n<li>extract database name from adr_home.<\/li>\n<\/ul>\n<p><em>V$DIAG_ALERT_EXT<\/em> displays the content of the alert logs of all of the databases on a server. Hence, if you&#8217;re uncomfortable with running commands on the production server you can transfer the xml version of the alert log to a test server and do all the analysis there. Similarly, if you&#8217;d like to focus your analysis on a single database, just add <em>where db=&#8217;DBNAME&#8217;<\/em> to the queries below.<\/p>\n<p>The information of the beginning and completion of a checkpoint is stored in two separate rows which makes it a bit awkward for reporting. Therefore, the following view does a self-join on the table <em>checkpoint_events<\/em> to encapsulate checkpoint information in a single row:<\/p>\n<pre><code>create or replace view checkpoints as\r\n    select b.db, \r\n        sysdate \r\n     +  ( c.originating_timestamp - b.originating_timestamp ) * 86400 \r\n     -  sysdate duration ,\r\n        b.originating_timestamp started,\r\n        c.originating_timestamp completed,\r\n        b.scn\r\n    from checkpoint_events b, checkpoint_events c \r\n    where b.event = 'Beginning' and c.event = 'Completed' \r\n\t\tand b.scn = c.scn and b.db = c.db ;\r\n<\/code><\/pre>\n<p>Also, the checkpoint duration in seconds has been added.<\/p>\n<p>For the data formatting you can user following settings:<\/p>\n<pre><code>alter session set NLS_TIMESTAMP_FORMAT='dd-MON-yy hh24:mi:ss' ;\r\n\r\ncolumn db format a6\r\ncolumn duration format 999999\r\ncolumn avg_duration format 999999\r\ncolumn started format a19                                                                                                                                                       \r\ncolumn completed format a19\r\ncolumn scn format 99999999999999<\/code><\/pre>\n<h1>Top 10 Checkpoints<\/h1>\n<p>Having the information properly prepared, displaying the longest running checkpoints becomes trivial:<\/p>\n<pre><code>select * from checkpoints order by duration desc fetch first 10 rows only ;\r\nDB     DURATION STARTED             COMPLETED           SCN\r\n------ -------- ------------------- ------------------- --------------\r\nDBXX7      1057 20-SEP-17 10:57:20  20-SEP-17 11:14:57  9236890926896\r\nDBXX9       798 18-SEP-17 22:56:43  18-SEP-17 23:10:00  9239503025928\r\nDBXX12      713 18-SEP-17 22:36:58  18-SEP-17 22:48:51  9239502835402\r\nDBPX1       575 11-SEP-17 20:45:55  11-SEP-17 20:55:30  9085573686452\r\nDBPX1       517 11-SEP-17 20:50:15  11-SEP-17 20:58:52  9085574034974\r\nDBPX1       457 16-SEP-17 09:39:31  16-SEP-17 09:47:08  9085912947207\r\nDBXX1       431 16-SEP-17 01:07:25  16-SEP-17 01:14:36  9231717131040\r\nDBXX4       430 20-SEP-17 00:01:37  20-SEP-17 00:08:46  9236909077807\r\nDBPX1       428 16-SEP-17 09:37:30  16-SEP-17 09:44:38  9085912733264\r\nDBPX1       421 21-SEP-17 20:47:03  21-SEP-17 20:54:04  9086255245605\r\n<\/code><\/pre>\n<h1>Concurrent Checkpoints<\/h1>\n<p>The next interesting information we can get from the view is the number of concurrent checkpoints over time. If this value is higher than the number of your redo log groups, the sessions are going to wait. Therefore, you should further analyze the intervals of high concurrency.<\/p>\n<pre><code>select distinct db,\r\n    case when \r\n        period_started between \r\n            lag(period_started,1) over (partition by db order by period_started)\r\n            and \r\n            lag(period_completed,1) over (partition by db order by period_started)\r\n        and cnt < lag(cnt,1) over (partition by db order by period_started)\r\n        then\r\n            lag(period_completed,1) over (partition by db order by period_started)\r\n        else\r\n            period_started\r\n        end as started,\r\n    case when \r\n        period_completed between \r\n            lead(period_started,1) over (partition by db order by period_started)\r\n            and \r\n            lead(period_completed,1) over (partition by db order by period_started)\r\n        and cnt < lead(cnt,1) over (partition by db order by period_started)\r\n        then\r\n            lead(period_started,1) over (partition by db order by period_started)\r\n        else\r\n            period_completed\r\n        end as completed,\r\n    cnt concurrency\r\nfrom\r\n(select v_concatenated.*,\r\n    last_value(concatenated_period_started) ignore nulls \r\n        over (\r\n            partition by db order by started \r\n            rows between unbounded preceding and current row \r\n        ) as period_started,\r\n    first_value(concatenated_period_completed) ignore nulls \r\n        over (\r\n            partition by db order by started \r\n            rows between current row and unbounded following \r\n        ) as period_completed \r\n from   \r\n( select v_grouped.*,\r\n    case when started \r\n        between \r\n            lag(started,1)   over (partition by db order by started) and \r\n            lag(completed,1) over (partition by db order by started) \r\n        and lag(cnt) over (partition by db order by started) = cnt\r\n        then NULL \r\n        else started \r\n    end as concatenated_period_started,\r\n    case when completed \r\n        between \r\n            lead(started,1)   over (partition by db order by started) and \r\n            lead(completed,1) over (partition by db order by started)\r\n        and lead(cnt) over (partition by db order by started) = cnt \r\n    then NULL \r\n    else completed \r\n    end as concatenated_period_completed  \r\n    from   \r\n        ( select c1.db,c1.started,c1.completed,count(*)+1 cnt\r\n            from checkpoints c1 inner join checkpoints c2 on c1.db = c2.db \r\n                and c2.started > c1.started and c2.started <= c1.completed \r\n            group by c1.db,c1.started,c1.completed\r\n        ) v_grouped\r\n) v_concatenated\r\n)\r\n    order by \r\n        concurrency desc, started \r\n\tfetch first 10 rows only\r\n;\r\n\r\nDB     STARTED             COMPLETED           CONCURRENCY\r\n------ ------------------- ------------------- -----------\r\nDBXX7  23-MAR-17 15:36:39  23-MAR-17 15:38:24            4\r\nDBXX8  05-JUN-17 20:28:14  05-JUN-17 20:34:27            4\r\nDBXX2  22-JUL-17 18:31:05  22-JUL-17 18:37:48            4\r\nDBXX2  11-AUG-17 10:51:20  11-AUG-17 11:01:35            4\r\nDBXX7  22-AUG-17 11:04:22  22-AUG-17 11:09:26            4\r\nDBXX7  28-AUG-17 08:57:02  28-AUG-17 09:02:08            4\r\nDBXX1  04-SEP-17 08:54:08  04-SEP-17 09:01:03            4\r\nDBXX7  05-SEP-17 10:02:11  05-SEP-17 10:08:48            4\r\nDBXX7  13-SEP-17 09:09:02  13-SEP-17 09:16:06            4\r\nDBXX12 14-SEP-17 16:47:07  14-SEP-17 16:51:12            4\r\n<\/code><\/pre>\n<p>Alternatively, you can change the order by clause to <em>order by started<\/em> to observe how the checkpoint concurrency changes with time:<\/p>\n<pre><code>DB     STARTED             COMPLETED           CONCURRENCY\r\n------ ------------------- ------------------- -----------\r\nDBXX7  23-MAR-17 15:13:53  23-MAR-17 15:18:58            2\r\nDBXX7  23-MAR-17 15:36:39  23-MAR-17 15:38:24            4\r\nDBXX7  23-MAR-17 15:38:24  23-MAR-17 15:42:09            3\r\nDBXX7  23-MAR-17 15:42:09  23-MAR-17 15:42:30            2\r\nDBXX8  09-MAY-17 02:00:04  09-MAY-17 02:05:07            2\r\nDBXX8  11-MAY-17 02:00:50  11-MAY-17 02:05:53            2\r\nDBXX8  16-MAY-17 02:21:50  16-MAY-17 02:26:54            2\r\nDBXX8  05-JUN-17 20:28:14  05-JUN-17 20:34:27            4\r\nDBXX8  05-JUN-17 20:34:27  05-JUN-17 20:35:00            3\r\nDBXX8  05-JUN-17 20:35:00  05-JUN-17 20:36:18            2\r\n<\/code><\/pre>\n<p>The most inner subquery named <em>v_grouped<\/em> filters out the time intervals of concurrent checkpoints by using the technique described in the <a href=\"https:\/\/stackoverflow.com\/questions\/4490553\/detect-overlapping-date-ranges-from-the-same-table\" target=\"_blank\" rel=\"noopener\">Stack Overflow question Detect Overlapping date ranges from the same table<\/a>. The outer subqueries use Oracle window analytic functions to concatenate and align adjacent time intervals. <\/p>\n<p>It was not until I had seen Lukas Eder's presentation and read his blog post <a href=\"https:\/\/blog.jooq.org\/2016\/04\/25\/10-sql-tricks-that-you-didnt-think-were-possible\/\" target=\"_blank\" rel=\"noopener\">10 SQL tricks that you-didnt think were possible<\/a> that I started using windows analytic functions for non-trivial data processing. <\/p>\n<h1>Time Intervals<\/h1>\n<p>Lastly, I'll be comparing checkpoint activity during different time intervals, whereby I'd like to avoid hard coding the duration of the interval. Sadly, unlike SQL Server, Oracle doesn't provide parametrized views, so I'm going to emulate the functionality by using a pipelined function:<\/p>\n<pre><code>create or replace type checkpoint_intervals_ty is object ( \r\n    db varchar2(9 byte), started timestamp, duration number, \r\n\tchkpt_count integer \r\n) ; \r\n\/\r\n\r\nCREATE OR REPLACE type checkpoint_intervals_tbl_ty is \r\n    table of checkpoint_intervals_ty; \r\n\/\r\n\r\nCREATE OR REPLACE FUNCTION checkpoint_intervals ( p_minutes integer) \r\n    RETURN checkpoint_intervals_tbl_ty PIPELINED AS\r\n  CURSOR cur (p_minutes integer)\r\n  IS\r\n    select db, \r\n        ( \r\n            trunc(started,'hh24') \r\n          + (trunc(to_char(started,'mi')\/p_minutes)*p_minutes)\/24\/60 \r\n        ) interval_start, \r\n        sum(duration) total_duration,\r\n        count(*) count_chkpts\r\n        from checkpoints\r\n        group by db,  \r\n            ( \r\n                trunc(started,'hh24') \r\n              + (trunc(to_char(started,'mi')\/p_minutes)*p_minutes)\/24\/60 \r\n            )\r\n    ;\r\nBEGIN\r\n    FOR rec IN cur (p_minutes) \r\n    LOOP\r\n       pipe row( checkpoint_intervals_ty (\r\n\t\trec.db,rec.interval_start,rec.total_duration,rec.count_chkpts\r\n\t   ));\r\n    END LOOP;\r\n    RETURN;\r\nEND;\r\n\/\r\n<\/code><\/pre>\n<p>Finally, we can easily get the information about the most intensive 30-minute time intervals by selecting from the pipelined function:<\/p>\n<pre><code>select t.*,t.duration\/t.chkpt_count avg_duration\r\n\tfrom table(checkpoint_intervals(30)) t\r\n\torder by duration desc \r\n\tfetch first 5 rows only ;\r\n\r\nDB     STARTED             DURATION CHKPT_COUNT AVG_DURATION\r\n------ ------------------- -------- ----------- ------------\r\nDBXX1  04-SEP-17 08:30:00      3597          12          300\r\nDBXX2  22-JUL-17 18:30:00      3341          11          304\r\nDBXX2  22-JUL-17 23:00:00      3051          10          305\r\nDBPX1  16-SEP-17 09:30:00      2861           8          358\r\nDBXX2  22-JUL-17 23:30:00      2785           9          309\r\n<\/code><\/pre>\n<p>Other useful sorting criteria might be the number of checkpoints and average duration of checkpoint, respectively, <em>chkpt_count desc<\/em> and <em>duration\/chkpt_count desc<\/em>:<\/p>\n<pre><code>\r\nDB     STARTED             DURATION CHKPT_COUNT AVG_DURATION\r\n------ ------------------- -------- ----------- ------------\r\nDBXX1  20-SEP-17 08:00:00      1811          13          139\r\nDBXX1  04-SEP-17 08:30:00      3597          12          300\r\nDBXX9  20-SEP-17 18:30:00      1472          12          123\r\nDBXX2  22-JUL-17 18:30:00      3341          11          304\r\nDBXX2  22-JUL-17 23:00:00      3051          10          305\r\n\r\nDB     STARTED             DURATION CHKPT_COUNT AVG_DURATION\r\n------ ------------------- -------- ----------- ------------\r\nDBXX7  20-SEP-17 10:30:00      1057           1         1057\r\nDBXX9  18-SEP-17 22:30:00       798           1          798\r\nDBXX12 18-SEP-17 22:30:00       713           1          713\r\nDBXX4  20-SEP-17 00:00:00       430           1          430\r\nDBPX1  11-SEP-17 20:30:00      1700           4          425\r\n<\/code><\/pre>\n<p>Here, I've used two techniques described on Ask TOM to implement data aggregation based on flexible time intervals by using a pipelined function:<\/p>\n<ul>\n<li><a href=\"https:\/\/asktom.oracle.com\/pls\/asktom\/f?p=100:11:0::::P11_QUESTION_ID:4222062043865\" target=\"_blank\" rel=\"noopener\">Summarizing data over time - by time interval<\/a><\/li>\n<li><a href=\"https:\/\/asktom.oracle.com\/pls\/asktom\/f?p=100:11:0::::P11_QUESTION_ID:906341500346611919\" target=\"_blank\" rel=\"noopener\">Parameterized views -vs- views with where conditions<\/a><\/li>\n<\/ul>\n<p>BTW, if you think parametrized views should be implemented in Oracle, you can vote for this idea <a href=\"https:\/\/community.oracle.com\/ideas\/11316\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Analyzing checkpoint information in alert log with SQL analytic functions <a href=\"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/\" class=\"more-link\">Continue Reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[5],"tags":[],"class_list":["post-1582","post","type-post","status-publish","format-standard","hentry","category-oracle"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Checkpoint Analytics - All-round Database Topics<\/title>\n<meta name=\"description\" content=\"Analyzing checkpoint information in alert log with SQL analytic functions\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Checkpoint Analytics - All-round Database Topics\" \/>\n<meta property=\"og:description\" content=\"Analyzing checkpoint information in alert log with SQL analytic functions\" \/>\n<meta property=\"og:url\" content=\"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/\" \/>\n<meta property=\"og:site_name\" content=\"All-round Database Topics\" \/>\n<meta property=\"article:published_time\" content=\"2017-10-02T22:07:36+00:00\" \/>\n<meta name=\"author\" content=\"Nenad Noveljic\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@NenadNoveljic\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nenad Noveljic\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/checkpoint-analytics\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/checkpoint-analytics\\\/\"},\"author\":{\"name\":\"Nenad Noveljic\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"headline\":\"Checkpoint Analytics\",\"datePublished\":\"2017-10-02T22:07:36+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/checkpoint-analytics\\\/\"},\"wordCount\":671,\"commentCount\":0,\"articleSection\":[\"Oracle\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/checkpoint-analytics\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/checkpoint-analytics\\\/\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/checkpoint-analytics\\\/\",\"name\":\"Checkpoint Analytics - All-round Database Topics\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\"},\"datePublished\":\"2017-10-02T22:07:36+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"description\":\"Analyzing checkpoint information in alert log with SQL analytic functions\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/checkpoint-analytics\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/checkpoint-analytics\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/checkpoint-analytics\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Checkpoint Analytics\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\",\"name\":\"All-round Database Topics\",\"description\":\"Nenad Noveljic\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\",\"name\":\"Nenad Noveljic\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"caption\":\"Nenad Noveljic\"},\"sameAs\":[\"nenad-noveljic-9b746a6\",\"https:\\\/\\\/x.com\\\/NenadNoveljic\"],\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/author\\\/nenad\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Checkpoint Analytics - All-round Database Topics","description":"Analyzing checkpoint information in alert log with SQL analytic functions","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/","og_locale":"en_US","og_type":"article","og_title":"Checkpoint Analytics - All-round Database Topics","og_description":"Analyzing checkpoint information in alert log with SQL analytic functions","og_url":"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/","og_site_name":"All-round Database Topics","article_published_time":"2017-10-02T22:07:36+00:00","author":"Nenad Noveljic","twitter_card":"summary_large_image","twitter_creator":"@NenadNoveljic","twitter_misc":{"Written by":"Nenad Noveljic","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/#article","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/"},"author":{"name":"Nenad Noveljic","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"headline":"Checkpoint Analytics","datePublished":"2017-10-02T22:07:36+00:00","mainEntityOfPage":{"@id":"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/"},"wordCount":671,"commentCount":0,"articleSection":["Oracle"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/","url":"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/","name":"Checkpoint Analytics - All-round Database Topics","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#website"},"datePublished":"2017-10-02T22:07:36+00:00","author":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"description":"Analyzing checkpoint information in alert log with SQL analytic functions","breadcrumb":{"@id":"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/nenadnoveljic.com\/blog\/checkpoint-analytics\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/nenadnoveljic.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Checkpoint Analytics"}]},{"@type":"WebSite","@id":"https:\/\/nenadnoveljic.com\/blog\/#website","url":"https:\/\/nenadnoveljic.com\/blog\/","name":"All-round Database Topics","description":"Nenad Noveljic","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/nenadnoveljic.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa","name":"Nenad Noveljic","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","caption":"Nenad Noveljic"},"sameAs":["nenad-noveljic-9b746a6","https:\/\/x.com\/NenadNoveljic"],"url":"https:\/\/nenadnoveljic.com\/blog\/author\/nenad\/"}]}},"_links":{"self":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/1582","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/comments?post=1582"}],"version-history":[{"count":1,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/1582\/revisions"}],"predecessor-version":[{"id":1617,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/1582\/revisions\/1617"}],"wp:attachment":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/media?parent=1582"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/categories?post=1582"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/tags?post=1582"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}