Skip to content

Commit d8ef04c

Browse files
authored
Merge pull request #1 from shane-borden/add_psql_scripts
Add psql scripts
2 parents 2fa2ef6 + 5bc4da1 commit d8ef04c

5 files changed

+736
-33
lines changed
Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
-- Copyright 2025 shaneborden
2+
--
3+
-- Licensed under the Apache License, Version 2.0 (the "License");
4+
-- you may not use this file except in compliance with the License.
5+
-- You may obtain a copy of the License at
6+
--
7+
-- https://www.apache.org/licenses/LICENSE-2.0
8+
--
9+
-- Unless required by applicable law or agreed to in writing, software
10+
-- distributed under the License is distributed on an "AS IS" BASIS,
11+
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
-- See the License for the specific language governing permissions and
13+
-- limitations under the License.
14+
15+
/* Helpful Links
16+
https://cloud.google.com/alloydb/docs/columnar-engine/manage-content-recommendations
17+
https://medium.com/google-cloud/alloydbs-columnar-store-how-to-preserve-it-during-failovers-and-restarts-141a8466772 */
18+
19+
/* determine columnar engine settings */
20+
select name,setting,boot_val,reset_val from pg_settings where name like '%google_columnar_engine%' order by 1;
21+
22+
/* Set a population policy */
23+
SELECT google_columnar_engine_add_policy('RECOMMEND_AND_POPULATE_COLUMNS','IMMEDIATE',0,'HOURS');
24+
--IMMEDIATE - runs immediately one time. When you use this value, specify 0 and 'HOURS' for the duration and time_unit parameters.
25+
--AFTER - runs once when the duration time_unit amount of time passes
26+
--EVERY - runs repeatedly every duration time_unit amount of time
27+
28+
/* Execute a recommendation */
29+
SELECT google_columnar_engine_run_recommendation(102400,'PERFORMANCE_OPTIMAL');
30+
31+
/* check from psql if columnar is enabled */
32+
postgres=# show google_columnar_engine.enabled;
33+
google_columnar_engine.enabled
34+
--------------------------------
35+
off
36+
37+
/* To show columnar messages in cloud logging */
38+
textPayload=~"population_jobs.cc|Invalidating columnar|population.cc|columnar"
39+
40+
/* To Force a SEQ Scan for invalid blocks; this is the default now; Use this for debugging only */
41+
set session google_columnar_engine.rowstore_scan_mode to 1;
42+
43+
/* To show the refresh threshold (based on invalid blocks vs total blocks) */
44+
show google_columnar_engine.refresh_threshold_percentage;
45+
46+
/* To show the number of DML operations on base table required before the refresh_threshold_percentage kicks in */
47+
show google_columnar_engine.refresh_threshold_scan_count;
48+
49+
/* to force a columnar scan; generally isnt needed, this is for testing / debugging only */
50+
set session google_columnar_engine.force_columnar_mode to true;
51+
52+
/* other GUC to influence CE costing, this is for testing / debugging only */
53+
set session enable_cache_aware_costing = true
54+
set session google_columnar_engine.bump_columnar_scan_cost = false
55+
56+
/* to force columnar using pg_hint_plan */
57+
/*+ ColumnarScan(xxx) */
58+
59+
/* To manually run the job: */
60+
SELECT google_columnar_engine_recommend();
61+
62+
/* To view the list of recommended columns: */
63+
SELECT * FROM g_columnar_recommended_columns;
64+
SELECT database_name, schema_name, relation_name, column_name FROM g_columnar_recommended_columns;
65+
66+
/* To add a table */
67+
SELECT google_columnar_engine_add('t1');
68+
select google_columnar_engine_add(relation => 'public.t1', in_background => TRUE);
69+
70+
/* To add a table with a subset of columns */
71+
SELECT google_columnar_engine_add('public.t1', 'a,b,c,f,');
72+
73+
/* To remove a table */
74+
SELECT google_columnar_engine_drop('t1');
75+
SELECT google_columnar_engine_drop('public.t1');
76+
77+
/* To disable columnar for a query in a session */
78+
set session google_columnar_engine.enable_columnar_scan TO 'off';
79+
80+
/* to Refresh a table */
81+
select google_columnar_engine_refresh('public.t1');
82+
83+
select google_columnar_engine_refresh(relation => 'public.t1', in_background => TRUE);
84+
85+
/* to check columar jobs */
86+
select * from g_columnar_jobs;
87+
88+
/* To view the list of recommended column detail: */
89+
SELECT
90+
crc.database_name as database_name,
91+
crc.schema_name AS schema_name,
92+
crc.relation_name AS table_name,
93+
pi.inhparent::regclass,
94+
crc.column_name,
95+
crc.column_format,
96+
crc.compression_level,
97+
crc.estimated_size_in_bytes
98+
FROM public.g_columnar_recommended_columns_internal /* g_columnar_recommended_columns */ crc
99+
JOIN pg_stat_all_tables ps
100+
ON ps.schemaname::text = crc.schema_name
101+
AND ps.relname::text = crc.relation_name
102+
JOIN pg_class pc
103+
ON ps.relid = pc.oid
104+
LEFT JOIN pg_catalog.pg_inherits pi
105+
ON ps.relid = pi.inhrelid
106+
ORDER BY 1,2,4 NULLS LAST;
107+
108+
/* to display table name without column detail */
109+
SELECT
110+
crc.database_name as database_name,
111+
crc.schema_name AS schema_name,
112+
crc.relation_name AS table_name,
113+
pi.inhparent::regclass,
114+
crc.column_format,
115+
crc.compression_level,
116+
SUM(crc.estimated_size_in_bytes) as total_bytes,
117+
pg_size_pretty(SUM(crc.estimated_size_in_bytes)) as pretty_total_size
118+
FROM g_columnar_recommended_columns crc
119+
JOIN pg_stat_all_tables ps
120+
ON ps.schemaname::text = crc.schema_name
121+
AND ps.relname::text = crc.relation_name
122+
JOIN pg_class pc
123+
ON ps.relid = pc.oid
124+
LEFT JOIN pg_catalog.pg_inherits pi
125+
ON ps.relid = pi.inhrelid
126+
GROUP BY crc.database_name, crc.schema_name, crc.relation_name, pi.inhparent::regclass,crc.column_format,crc.compression_level
127+
ORDER BY 1,2,4 NULLS LAST;
128+
129+
130+
/* List of items in the column store */
131+
SELECT
132+
database_name,
133+
schema_name,
134+
relation_name,
135+
column_name,
136+
column_type,
137+
status,
138+
size_in_bytes,
139+
last_accessed_time,
140+
num_times_accessed
141+
FROM
142+
g_columnar_columns;
143+
144+
SELECT
145+
*
146+
FROM
147+
g_columnar_columns;
148+
149+
SELECT
150+
*
151+
FROM
152+
g_columnar_relations
153+
ORDER BY
154+
relation_name;
155+
156+
157+
/* To see current status of items in columnstore */
158+
SELECT
159+
schema_name,
160+
relation_name,
161+
status,
162+
swap_status,
163+
sum(end_block - start_block) ttl_block,
164+
sum(invalid_block_count) invalid_block,
165+
CASE WHEN sum(end_block - start_block) > 0 THEN
166+
round(100 * sum(invalid_block_count) / sum(end_block - start_block), 1)
167+
ELSE 0.0
168+
END AS invalid_block_perc,
169+
pg_size_pretty(sum(size)) ttl_size,
170+
pg_size_pretty(sum(cached_size_bytes)) ttl_cached_size
171+
FROM
172+
g_columnar_units
173+
WHERE
174+
g_columnar_units.database_name = current_database()
175+
and g_columnar_units.relation_name like '%'
176+
GROUP BY
177+
schema_name,
178+
relation_name,
179+
status,
180+
swap_status
181+
ORDER BY
182+
relation_name;
183+
184+
/* Check utilization of columnar memory */
185+
SELECT
186+
memory_name,
187+
memory_total / 1024 / 1024 memory_total_MB,
188+
memory_available / 1024 / 1024 memory_available_MB,
189+
memory_available_percentage,
190+
pg_size_pretty(google_columnar_engine_storage_cache_used()*1024*1024) AS cc_storage_cache_used_mb,
191+
pg_size_pretty(google_columnar_engine_storage_cache_available()*1024*1024) AS cc_storage_cache_avail_mb,
192+
pg_size_pretty((google_columnar_engine_storage_cache_available() - google_columnar_engine_storage_cache_used())*1024*1024) as cc_storage_cache_free_mb
193+
FROM
194+
g_columnar_memory_usage;
195+
196+
/* Check non default "google" postgres params */
197+
SELECT
198+
s.name AS "Parameter",
199+
pg_catalog.current_setting(s.name) AS "Value"
200+
FROM
201+
pg_catalog.pg_settings s
202+
WHERE
203+
1=1
204+
--AND s.source <> 'default'
205+
--AND s.setting IS DISTINCT FROM s.boot_val
206+
AND lower(s.name) LIKE '%google%'
207+
ORDER BY
208+
1;
209+
210+
/* To see Columnar engine column Swap-out */
211+
SELECT
212+
memory_name,
213+
pg_size_pretty(memory_total) AS cc_allocated,
214+
pg_size_pretty(memory_total - memory_available) AS cc_consumed,
215+
pg_size_pretty(memory_available) cc_available,
216+
--google_columnar_engine_storage_cache_total() as cc_storage_cache_avail_mb, /* Future function */
217+
google_columnar_engine_storage_cache_used() AS cc_storage_cache_used_mb,
218+
google_columnar_engine_storage_cache_available() AS cc_storage_cache_avail_mb,
219+
CASE WHEN google_columnar_engine_storage_cache_used() > 0 THEN
220+
'Swapped-out Column(s)'
221+
ELSE
222+
NULL
223+
END AS "SwapOut",
224+
(
225+
SELECT
226+
CONCAT_WS('-', STRING_AGG(DISTINCT g_columnar_units.relation_name, '/'), STATUS, swap_status)
227+
FROM
228+
g_columnar_units
229+
GROUP BY
230+
status,
231+
swap_status) AS current_obj
232+
FROM
233+
g_columnar_memory_usage
234+
WHERE
235+
memory_name = 'main_pool';
236+
237+
238+
/* To populate many tables manually */
239+
do
240+
$$
241+
declare
242+
f record;
243+
gResult numeric;
244+
begin_timestamp timestamp;
245+
age_text text;
246+
begin
247+
for f in SELECT
248+
n.nspname as schemaname,
249+
c.oid::regclass::text AS table_name,
250+
c.oid as oid,
251+
pi.inhparent::regclass::text AS top_table_name,
252+
pg_total_relation_size(c.oid) as size,
253+
pg_size_pretty(pg_total_relation_size(c.oid)) as pretty_size
254+
FROM pg_class c
255+
JOIN pg_namespace n on c.relnamespace = n.oid
256+
LEFT JOIN pg_inherits pi on c.oid = pi.inhrelid
257+
WHERE c.relkind IN ('r', 't', 'm')
258+
AND (n.nspname NOT IN('pg_toast') AND n.nspname LIKE '%')
259+
--AND (c.oid::regclass::text LIKE '%' AND pi.inhparent::regclass::text LIKE '%')
260+
AND (c.oid::regclass::text LIKE 'table_name%' AND pi.inhparent::regclass::text LIKE 'table_partiton_name%')
261+
ORDER BY 2 NULLS LAST
262+
loop
263+
BEGIN
264+
SELECT clock_timestamp() into begin_timestamp;
265+
--SELECT google_columnar_engine_add(f.oid,'[comma separated column list]') into gResult; /* us this if there are specific cols */
266+
SELECT google_columnar_engine_add(f.oid) into gResult;
267+
SELECT age(clock_timestamp(),begin_timestamp)::text into age_text;
268+
raise notice ' % % % % % %', f.top_table_name, f.table_name, 'google_columnar_engine_add result: ', gResult, ' time: ', age_text;
269+
EXCEPTION WHEN OTHERS THEN
270+
raise notice ' % % % %', f.top_table_name, f.table_name, 'exception result', gResult;
271+
END;
272+
end loop;
273+
end;
274+
$$;
275+
276+
277+
/* To refresh many tables manually */
278+
do
279+
$$
280+
declare
281+
f record;
282+
gResult numeric;
283+
begin
284+
for f in SELECT
285+
n.nspname as schemaname,
286+
c.oid::regclass::text AS table_name,
287+
c.oid as oid,
288+
pi.inhparent::regclass::text AS top_table_name,
289+
pg_total_relation_size(c.oid) as size,
290+
pg_size_pretty(pg_total_relation_size(c.oid)) as pretty_size
291+
FROM pg_class c
292+
JOIN pg_namespace n on c.relnamespace = n.oid
293+
LEFT JOIN pg_inherits pi on c.oid = pi.inhrelid
294+
WHERE c.relkind IN ('r', 't', 'm')
295+
AND (n.nspname NOT IN('pg_toast') AND n.nspname LIKE '%')
296+
--AND (c.oid::regclass::text LIKE '%' AND pi.inhparent::regclass::text LIKE '%')
297+
AND (c.oid::regclass::text LIKE 'table_name%' AND pi.inhparent::regclass::text LIKE 'table_partiton_name%')
298+
ORDER BY 2 NULLS LAST
299+
loop
300+
BEGIN
301+
SELECT google_columnar_engine_refresh(f.oid) into gResult;
302+
raise notice ' % % % %', f.top_table_name, f.table_name, 'google_columnar_engine_refresh result: ', gResult;
303+
EXCEPTION WHEN OTHERS THEN
304+
raise notice ' % % % %', f.top_table_name, f.table_name, 'exception result', gResult;
305+
END;
306+
end loop;
307+
end;
308+
$$;
309+
310+
/* To drop many tables manually */
311+
do
312+
$$
313+
declare
314+
f record;
315+
gResult numeric;
316+
begin
317+
for f in SELECT
318+
n.nspname as schemaname,
319+
c.oid::regclass::text AS table_name,
320+
c.oid as oid,
321+
pi.inhparent::regclass::text AS top_table_name,
322+
pg_total_relation_size(c.oid) as size,
323+
pg_size_pretty(pg_total_relation_size(c.oid)) as pretty_size
324+
FROM pg_class c
325+
JOIN pg_namespace n on c.relnamespace = n.oid
326+
LEFT JOIN pg_inherits pi on c.oid = pi.inhrelid
327+
JOIN g_columnar_units ce on (ce.schema_name = n.nspname and ce.relation_name = c.oid::regclass::text)
328+
WHERE c.relkind IN ('r', 't', 'm')
329+
AND (n.nspname NOT IN('pg_toast') AND n.nspname LIKE '%')
330+
--AND (c.oid::regclass::text LIKE '%' AND pi.inhparent::regclass::text LIKE '%')
331+
AND (c.oid::regclass::text LIKE 'table_name%' AND pi.inhparent::regclass::text LIKE 'table_partiton_name%')
332+
ORDER BY 2 NULLS LAST
333+
loop
334+
BEGIN
335+
SELECT google_columnar_engine_drop(f.oid) into gResult;
336+
raise notice ' % % % %', f.top_table_name, f.table_name, 'google_columnar_engine_add result: ', gResult;
337+
EXCEPTION WHEN OTHERS THEN
338+
raise notice ' % % % %', f.top_table_name, f.table_name, 'exception result', gResult;
339+
END;
340+
end loop;
341+
end;
342+
$$;

0 commit comments

Comments
 (0)