⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 203148 in webkit


Ignore:
Timestamp:
Jul 12, 2016, 8:30:00 PM (10 years ago)
Author:
Lucas Forschler
Message:

<rdar://problem/22524456> Mitigate performance degradation of the flakiness dashboard

Rubber-stamped by Dean Johnson.

  • init-database.sql:

Rewrite the init-database.sql file to allow for table partitioning, based on insert date.
Some important things to note:

The main results table is unchanged, but will no longer contain any rows.
Partitioned tables will be generated on demand, and will inherit from 'results'
It is possible to query the 'results' table directly, and that will get data from all child tables.
This should keep us from requiring any client side code changes.


  • public_partition_maintenance: Added.

Maintenance script which will be called on a nightly schedule to purge expired data.
This data will be exported and compressed to a sub-folder, then dropped from the database.
I'm not sure how big it will be, so we'll likely need to keep an eye on it.


  • test-database.sql: Added.

Simple helper function to test that results partitions are created/deleted correctly.

Location:
trunk/Websites/test-results
Files:
2 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Websites/test-results/ChangeLog

    r192180 r203148  
     12016-07-12  Lucas Forschler  <lforschler@apple.com>
     2
     3        <rdar://problem/22524456> Mitigate performance degradation of the flakiness dashboard
     4       
     5        Rubber-stamped by Dean Johnson.
     6
     7        * init-database.sql:
     8            Rewrite the init-database.sql file to allow for table partitioning, based on insert date.
     9            Some important things to note:
     10                The main results table is unchanged, but will no longer contain any rows.
     11                Partitioned tables will be generated on demand, and will inherit from 'results'
     12                It is possible to query the 'results' table directly, and that will get data from all child tables.
     13                This should keep us from requiring any client side code changes.
     14               
     15        * public_partition_maintenance: Added.
     16            Maintenance script which will be called on a nightly schedule to purge expired data.
     17            This data will be exported and compressed to a sub-folder, then dropped from the database.
     18            I'm not sure how big it will be, so we'll likely need to keep an eye on it.
     19           
     20        * test-database.sql: Added.
     21            Simple helper function to test that results partitions are created/deleted correctly.
     22
    1232015-11-09  Ryosuke Niwa  <rniwa@webkit.org>
    224
  • trunk/Websites/test-results/init-database.sql

    r188230 r203148  
    1 DROP TABLE results CASCADE;
    2 DROP TABLE tests CASCADE;
    3 DROP TABLE build_revisions CASCADE;
    4 DROP TABLE builds CASCADE;
    5 DROP TABLE slaves CASCADE;
    6 DROP TABLE repositories CASCADE;
    7 DROP TABLE builders CASCADE;
     1-- Configuration file for postgres
     2
     3-- Drop existing schema. WARNING: this will delete all data in the database
     4DROP SCHEMA IF EXISTS public CASCADE;
     5CREATE SCHEMA public;
     6
     7SET search_path TO public;
     8SET constraint_exclusion = partition;
     9SET work_mem='1GB';
     10
     11CREATE EXTENSION plsh;
    812
    913CREATE TABLE builders (
     
    6569CREATE INDEX results_is_flaky ON results(is_flaky);
    6670
    67 SET work_mem='1024MB';
     71-- Code specific to the table partitioning functions below were borrowed from:
     72-- https://blog.engineyard.com/2013/scaling-postgresql-performance-table-partitioning
     73CREATE OR REPLACE FUNCTION
     74public.server_partition_function()
     75RETURNS TRIGGER AS
     76$BODY$
     77DECLARE
     78_new_time int;
     79_tablename text;
     80_startdate text;
     81_enddate text;
     82_result record;
     83BEGIN
     84_tablename := 'results_partition_'||CURRENT_DATE;
     85
     86-- Check if the partition needed for the current record exists
     87PERFORM 1
     88FROM   pg_catalog.pg_class c
     89JOIN   pg_catalog.pg_namespace n ON n.oid = c.relnamespace
     90WHERE  c.relkind = 'r'
     91AND    c.relname = _tablename
     92AND    n.nspname = 'public';
     93
     94-- If the partition needed does not yet exist, then we create it:
     95-- Note that || is string concatenation (joining two strings to make one)
     96IF NOT FOUND THEN
     97_enddate:=_startdate::timestamp + INTERVAL '1 day';
     98EXECUTE 'CREATE TABLE public.' || quote_ident(_tablename) || ' (
     99) INHERITS (public.results)';
     100
     101-- Table permissions are not inherited from the parent.
     102-- If permissions change on the master be sure to change them on the child also.
     103EXECUTE 'ALTER TABLE public.' || quote_ident(_tablename) || ' OWNER TO test-results-user';
     104EXECUTE 'GRANT ALL ON TABLE public.' || quote_ident(_tablename) || ' TO test-results-user';
     105
     106-- Indexes are defined per child, so we assign a default index that uses the partition columns
     107EXECUTE 'CREATE INDEX ' || quote_ident(_tablename||'_indx1') || ' ON public.' || quote_ident(_tablename) || ' (time, id)';
     108END IF;
     109
     110-- Insert the current record into the correct partition, which we are sure will now exist.
     111EXECUTE 'INSERT INTO public.' || quote_ident(_tablename) || ' VALUES ($1.*)' USING NEW;
     112RETURN NULL;
     113END;
     114$BODY$
     115LANGUAGE plpgsql;
     116
     117
     118CREATE TRIGGER results_trigger
     119BEFORE INSERT ON public.results
     120FOR EACH ROW EXECUTE PROCEDURE public.server_partition_function();
     121
     122
     123-- Maintenance function
     124CREATE OR REPLACE FUNCTION
     125public.partition_maintenance(in_tablename_prefix text, in_master_tablename text, in_asof date)
     126RETURNS text AS
     127$BODY$
     128DECLARE
     129_result record;
     130_current_time_without_special_characters text;
     131_out_filename text;
     132_return_message text;
     133return_message text;
     134BEGIN
     135-- Get the current date in YYYYMMDD_HHMMSS.ssssss format
     136_current_time_without_special_characters :=
     137REPLACE(REPLACE(REPLACE(NOW()::TIMESTAMP WITHOUT TIME ZONE::TEXT, '-', ''), ':', ''), ' ', '_');
     138
     139-- Initialize the return_message to empty to indicate no errors hit
     140_return_message := '';
     141
     142--Validate input to function
     143IF in_tablename_prefix IS NULL THEN
     144RETURN 'Child table name prefix must be provided'::text;
     145ELSIF in_master_tablename IS NULL THEN
     146RETURN 'Master table name must be provided'::text;
     147ELSIF in_asof IS NULL THEN
     148RETURN 'You must provide the as-of date, NOW() is the typical value';
     149END IF;
     150
     151FOR _result IN SELECT * FROM pg_tables WHERE schemaname='public' LOOP
     152
     153IF POSITION(in_tablename_prefix in _result.tablename) > 0 AND char_length(substring(_result.tablename from '[0-9-]*$')) <> 0 AND (in_asof - interval '90 days') > to_timestamp(substring(_result.tablename from '[0-9-]*$'),'YYYY-MM-DD') THEN
     154
     155_out_filename := '/Volumes/Data/postgres/partition_dump/' || _result.tablename || '_' || _current_time_without_special_characters || '.sql.gz';
     156BEGIN
     157-- Call function export_partition(child_table text) to export the file
     158PERFORM public.export_partition(_result.tablename::text, _out_filename::text);
     159-- If the export was successful drop the child partition
     160EXECUTE 'DROP TABLE public.' || quote_ident(_result.tablename);
     161_return_message := return_message || 'Dumped table: ' || _result.tablename::text || ', ';
     162RAISE NOTICE 'Dumped table %', _result.tablename::text;
     163EXCEPTION WHEN OTHERS THEN
     164_return_message := return_message || 'ERROR dumping table: ' || _result.tablename::text || ', ';
     165RAISE NOTICE 'ERROR DUMPING %', _result.tablename::text;
     166END;
     167END IF;
     168END LOOP;
     169
     170RETURN _return_message || 'Done'::text;
     171END;
     172$BODY$
     173LANGUAGE plpgsql VOLATILE COST 100;
     174
     175ALTER FUNCTION public.partition_maintenance(text, text, date) OWNER TO test-results-user;
     176
     177GRANT EXECUTE ON FUNCTION public.partition_maintenance(text, text, date) TO test-results-user;
     178GRANT EXECUTE ON FUNCTION public.partition_maintenance(text, text, date) TO test-results-user;
     179
     180-- The function below is again generic and allows you to pass in the table name of the file you would like to export to the operating system and the name of the compressed file that will contain the exported table.
     181-- Helper Function for partition maintenance
     182CREATE OR REPLACE FUNCTION public.export_partition(text, text) RETURNS text AS
     183$BASH$
     184#!/bin/bash
     185tablename=${1}
     186filename=${2}
     187# NOTE: pg_dump must be available in the path.
     188/usr/local/bin/pg_dump -U test-results-user -t public."${tablename}" test-results-user | gzip -c > ${filename} ;
     189$BASH$
     190LANGUAGE plsh;
     191
     192ALTER FUNCTION public.export_partition(text, text) OWNER TO test-results-user;
     193
     194GRANT EXECUTE ON FUNCTION public.export_partition(text, text) TO test-results-user;
     195GRANT EXECUTE ON FUNCTION public.export_partition(text, text) TO test-results-user;
Note: See TracChangeset for help on using the changeset viewer.