Commit babe360507415e075f273fd176f705be404e3801
Committed by
Andrew Shvayka
1 parent
228fddb8
events: performance improvements: UI fast response with latest events, ttl clean…
…up speedup (with schema update)
Showing
5 changed files
with
139 additions
and
2 deletions
1 | +-- | |
2 | +-- Copyright © 2016-2021 The Thingsboard Authors | |
3 | +-- | |
4 | +-- Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +-- you may not use this file except in compliance with the License. | |
6 | +-- You may obtain a copy of the License at | |
7 | +-- | |
8 | +-- http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +-- | |
10 | +-- Unless required by applicable law or agreed to in writing, software | |
11 | +-- distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +-- See the License for the specific language governing permissions and | |
14 | +-- limitations under the License. | |
15 | +-- | |
16 | + | |
17 | +-- PROCEDURE: public.cleanup_events_by_ttl(bigint, bigint, bigint) | |
18 | + | |
19 | +DROP PROCEDURE IF EXISTS public.cleanup_events_by_ttl(bigint, bigint, bigint); | |
20 | + | |
21 | +CREATE OR REPLACE PROCEDURE public.cleanup_events_by_ttl( | |
22 | + ttl bigint, | |
23 | + debug_ttl bigint, | |
24 | + INOUT deleted bigint) | |
25 | +LANGUAGE 'plpgsql' | |
26 | +AS $BODY$ | |
27 | +DECLARE | |
28 | + ttl_ts bigint; | |
29 | + debug_ttl_ts bigint; | |
30 | + ttl_deleted_count bigint DEFAULT 0; | |
31 | + debug_ttl_deleted_count bigint DEFAULT 0; | |
32 | +BEGIN | |
33 | + IF ttl > 0 THEN | |
34 | + ttl_ts := (EXTRACT(EPOCH FROM current_timestamp) * 1000 - ttl::bigint * 1000)::bigint; | |
35 | + | |
36 | + DELETE FROM event | |
37 | + WHERE ts < ttl_ts | |
38 | + AND NOT event_type IN ('DEBUG_RULE_NODE', 'DEBUG_RULE_CHAIN', 'DEBUG_CONVERTER', 'DEBUG_INTEGRATION'); | |
39 | + | |
40 | + GET DIAGNOSTICS ttl_deleted_count = ROW_COUNT; | |
41 | + END IF; | |
42 | + | |
43 | + IF debug_ttl > 0 THEN | |
44 | + debug_ttl_ts := (EXTRACT(EPOCH FROM current_timestamp) * 1000 - debug_ttl::bigint * 1000)::bigint; | |
45 | + | |
46 | + DELETE FROM event | |
47 | + WHERE ts < debug_ttl_ts | |
48 | + AND event_type IN ('DEBUG_RULE_NODE', 'DEBUG_RULE_CHAIN', 'DEBUG_CONVERTER', 'DEBUG_INTEGRATION'); | |
49 | + | |
50 | + GET DIAGNOSTICS debug_ttl_deleted_count = ROW_COUNT; | |
51 | + END IF; | |
52 | + | |
53 | + RAISE NOTICE 'Events removed by ttl: %', ttl_deleted_count; | |
54 | + RAISE NOTICE 'Debug Events removed by ttl: %', debug_ttl_deleted_count; | |
55 | + deleted := ttl_deleted_count + debug_ttl_deleted_count; | |
56 | +END | |
57 | +$BODY$; | |
58 | + | |
59 | + | |
60 | +-- Index: idx_event_ts | |
61 | + | |
62 | +DROP INDEX IF EXISTS public.idx_event_ts; | |
63 | + | |
64 | +-- Hint: add CONCURRENTLY to CREATE INDEX query in case of more then 1 million records or during live update | |
65 | +-- CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_event_ts | |
66 | +CREATE INDEX IF NOT EXISTS idx_event_ts | |
67 | + ON public.event USING btree | |
68 | + (ts DESC NULLS LAST) | |
69 | + WITH (FILLFACTOR=95); | |
70 | + | |
71 | +COMMENT ON INDEX public.idx_event_ts | |
72 | + IS 'This index helps to delete events by TTL using timestamp'; | |
73 | + | |
74 | + | |
75 | +-- Index: idx_event_tenant_entity_type_entity_event_type_created_time_des | |
76 | + | |
77 | +DROP INDEX IF EXISTS public.idx_event_tenant_entity_type_entity_event_type_created_time_des; | |
78 | + | |
79 | +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_event_tenant_entity_type_entity_event_type_created_time_des | |
80 | +CREATE INDEX IF NOT EXISTS idx_event_tenant_entity_type_entity_event_type_created_time_des | |
81 | + ON public.event USING btree | |
82 | + (tenant_id ASC NULLS LAST, entity_type ASC NULLS LAST, entity_id ASC NULLS LAST, event_type ASC NULLS LAST, created_time DESC NULLS LAST) | |
83 | + WITH (FILLFACTOR=95); | |
84 | + | |
85 | +COMMENT ON INDEX public.idx_event_tenant_entity_type_entity_event_type_created_time_des | |
86 | + IS 'This index helps to open latest events on UI fast'; | |
87 | + | |
88 | +-- Index: idx_event_type_entity_id | |
89 | +-- Description: replaced with more suitable idx_event_tenant_entity_type_entity_event_type_created_time_des | |
90 | +DROP INDEX IF EXISTS public.idx_event_type_entity_id; | |
\ No newline at end of file | ... | ... |
... | ... | @@ -465,6 +465,17 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService |
465 | 465 | log.error("Failed updating schema!!!", e); |
466 | 466 | } |
467 | 467 | break; |
468 | + case "3.3.0": | |
469 | + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) { | |
470 | + log.info("Updating schema ..."); | |
471 | + log.info("Updating indexes and procedure for event table..."); | |
472 | + schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.3.0", "schema_update_event.sql"); | |
473 | + loadSql(schemaUpdateFile, conn); | |
474 | + log.info("Schema updated."); | |
475 | + } catch (Exception e) { | |
476 | + log.error("Failed updating schema!!!", e); | |
477 | + } | |
478 | + break; | |
468 | 479 | default: |
469 | 480 | throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); |
470 | 481 | } | ... | ... |
... | ... | @@ -45,7 +45,7 @@ public class EventsCleanUpService extends AbstractCleanUpService { |
45 | 45 | this.eventService = eventService; |
46 | 46 | } |
47 | 47 | |
48 | - @Scheduled(initialDelayString = "${sql.ttl.events.execution_interval_ms}", fixedDelayString = "${sql.ttl.events.execution_interval_ms}") | |
48 | + @Scheduled(initialDelayString = "#{T(org.apache.commons.lang3.RandomUtils).nextLong(0, ${sql.ttl.events.execution_interval_ms})}", fixedDelayString = "${sql.ttl.events.execution_interval_ms}") | |
49 | 49 | public void cleanUp() { |
50 | 50 | if (ttlTaskExecutionEnabled && isSystemTenantPartitionMine()) { |
51 | 51 | eventService.cleanupEvents(ttl, debugTtl); | ... | ... |
... | ... | @@ -266,7 +266,7 @@ sql: |
266 | 266 | ts_key_value_ttl: "${SQL_TTL_TS_TS_KEY_VALUE_TTL:0}" # Number of seconds |
267 | 267 | events: |
268 | 268 | enabled: "${SQL_TTL_EVENTS_ENABLED:true}" |
269 | - execution_interval_ms: "${SQL_TTL_EVENTS_EXECUTION_INTERVAL:86400000}" # Number of milliseconds. The current value corresponds to one day | |
269 | + execution_interval_ms: "${SQL_TTL_EVENTS_EXECUTION_INTERVAL:2220000}" # Number of milliseconds (max random initial delay and fixed period). # 37minutes to avoid common interval spikes | |
270 | 270 | events_ttl: "${SQL_TTL_EVENTS_EVENTS_TTL:0}" # Number of seconds |
271 | 271 | debug_events_ttl: "${SQL_TTL_EVENTS_DEBUG_EVENTS_TTL:604800}" # Number of seconds. The current value corresponds to one week |
272 | 272 | edge_events: | ... | ... |
application/src/test/java/org/thingsboard/server/service/ttl/EventsCleanUpServiceTest.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.service.ttl; | |
17 | + | |
18 | +import lombok.extern.slf4j.Slf4j; | |
19 | +import org.junit.Test; | |
20 | + | |
21 | +import static org.hamcrest.MatcherAssert.assertThat; | |
22 | +import static org.hamcrest.Matchers.greaterThanOrEqualTo; | |
23 | +import static org.hamcrest.Matchers.lessThanOrEqualTo; | |
24 | + | |
25 | +@Slf4j | |
26 | +public class EventsCleanUpServiceTest { | |
27 | + | |
28 | + @Test | |
29 | + public void givenInterval_whenRandomDelay_ThenDelayInInterval() { | |
30 | + final long executionIntervalMs = 2220000; //37min | |
31 | + final long randomDelay = org.apache.commons.lang3.RandomUtils.nextLong(0, executionIntervalMs); //same as @Scheduled(initialDelayString = ... | |
32 | + log.info("randomDelay {}", randomDelay); | |
33 | + assertThat(randomDelay, greaterThanOrEqualTo(0L)); | |
34 | + assertThat(randomDelay, lessThanOrEqualTo(executionIntervalMs)); | |
35 | + } | |
36 | +} | ... | ... |