db: add user_actions view.
Add a user_actions view. This view unions together a bunch of tables to produce an event log of every action taken by a user. Also add a bunch of indexes to make queries on this table efficient. Even though the view is an enormous query combining together about 30 different tables, queries are very efficient as long as every table has `created_at` and `(user_id, created)` indexes.
This commit is contained in:
67
db/migrate/20220913191309_create_user_actions.rb
Normal file
67
db/migrate/20220913191309_create_user_actions.rb
Normal file
@@ -0,0 +1,67 @@
|
||||
class CreateUserActions < ActiveRecord::Migration[7.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def change
|
||||
create_view :user_actions
|
||||
|
||||
add_index :bans, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :bulk_update_requests, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :dmails, :created_at, algorithm: :concurrently, where: "owner_id = from_id", name: "index_sent_dmails_on_created_at", if_not_exists: true
|
||||
add_index :favorite_groups, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :forum_posts, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :forum_post_votes, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :forum_topics, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :moderation_reports, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :post_approvals, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :post_disapprovals, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :post_flags, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :post_replacements, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :saved_searches, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :tag_aliases, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :tag_implications, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :tag_versions, :created_at, algorithm: :concurrently, where: "updater_id IS NOT NULL", name: "index_tag_versions_on_created_at_where_updater_id_is_not_null", if_not_exists: true
|
||||
add_index :users, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :user_events, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :user_feedback, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :uploads, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
add_index :user_upgrades, :created_at, algorithm: :concurrently, where: "status IN (20, 30)", name: "index_completed_user_upgrades_on_created_at", if_not_exists: true
|
||||
add_index :user_name_change_requests, :created_at, algorithm: :concurrently, if_not_exists: true
|
||||
|
||||
add_index :artist_versions, [:updater_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :artist_commentary_versions, [:updater_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :bans, [:user_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :bulk_update_requests, [:user_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :comments, [:creator_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :comment_votes, [:user_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :dmails, [:owner_id, :created_at], algorithm: :concurrently, where: "owner_id = from_id", name: "index_sent_dmails_on_owner_id_and_created_at", if_not_exists: true
|
||||
add_index :favorite_groups, [:created_at, :id, :is_public, :creator_id], algorithm: :concurrently, name: "index_favorite_groups_on_created_at_id_is_public_creator_id", if_not_exists: true
|
||||
add_index :forum_posts, [:creator_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :forum_post_votes, [:creator_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :forum_topics, [:creator_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :mod_actions, [:creator_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :moderation_reports, [:creator_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :note_versions, [:updater_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :posts, [:uploader_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :post_appeals, [:creator_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :post_approvals, [:user_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :post_disapprovals, [:user_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :post_flags, [:creator_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :post_replacements, [:creator_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :post_votes, [:user_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :saved_searches, [:user_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :tag_aliases, [:creator_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :tag_implications, [:creator_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :tag_versions, [:updater_id, :created_at], algorithm: :concurrently, where: "updater_id IS NOT NULL", name: "index_tag_versions_on_updater_id_and_created_at", if_not_exists: true
|
||||
add_index :uploads, [:uploader_id, :created_at, :id], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :users, [:id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :user_events, [:user_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :user_feedback, [:user_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :user_feedback, [:creator_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :user_upgrades, [:purchaser_id, :created_at], algorithm: :concurrently, where: "status IN (20, 30)", name: "index_completed_user_upgrades_on_updater_id_and_created_at", if_not_exists: true
|
||||
add_index :user_name_change_requests, [:user_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :wiki_page_versions, [:updater_id, :created_at], algorithm: :concurrently, if_not_exists: true
|
||||
|
||||
add_index :forum_posts, [:topic_id, :id], algorithm: :concurrently, if_not_exists: true
|
||||
add_index :users, :bit_prefs, where: "get_bit(bit_prefs::bit(31), 24) = 1", algorithm: :concurrently, name: "index_users_on_enable_private_favorites", if_not_exists: true # users.enable_private_favorites = true
|
||||
end
|
||||
end
|
||||
725
db/structure.sql
725
db/structure.sql
File diff suppressed because it is too large
Load Diff
105
db/views/user_actions_v01.sql
Normal file
105
db/views/user_actions_v01.sql
Normal file
@@ -0,0 +1,105 @@
|
||||
SELECT 'ArtistVersion'::character varying AS model_type, id AS model_id, updater_id AS user_id, 'create'::character varying AS event_type, created_at AS event_at
|
||||
FROM artist_versions
|
||||
UNION ALL
|
||||
SELECT 'ArtistCommentaryVersion', id, updater_id, 'create', created_at
|
||||
FROM artist_commentary_versions
|
||||
UNION ALL
|
||||
SELECT 'Ban', id, user_id, 'subject', created_at
|
||||
FROM bans
|
||||
UNION ALL
|
||||
SELECT 'BulkUpdateRequest', id, user_id, 'create', created_at
|
||||
FROM bulk_update_requests
|
||||
UNION ALL
|
||||
SELECT 'Comment', id, creator_id, 'create', created_at
|
||||
FROM comments
|
||||
UNION ALL
|
||||
SELECT 'CommentVote', id, user_id, 'create', created_at
|
||||
FROM comment_votes
|
||||
UNION ALL (
|
||||
SELECT 'Dmail', id, from_id, 'create', created_at
|
||||
FROM dmails
|
||||
WHERE from_id != owner_id
|
||||
ORDER BY created_at DESC
|
||||
)
|
||||
UNION ALL
|
||||
SELECT 'FavoriteGroup', id, creator_id, 'create', created_at
|
||||
FROM favorite_groups
|
||||
UNION ALL
|
||||
SELECT 'ForumPost', id, creator_id, 'create', created_at
|
||||
FROM forum_posts
|
||||
UNION ALL
|
||||
SELECT 'ForumPostVote', id, creator_id, 'create', created_at
|
||||
FROM forum_post_votes
|
||||
UNION ALL
|
||||
SELECT 'ForumTopic', id, creator_id, 'create', created_at
|
||||
FROM forum_topics
|
||||
UNION ALL
|
||||
SELECT 'ModAction', id, creator_id, 'create', created_at
|
||||
FROM mod_actions
|
||||
UNION ALL
|
||||
SELECT 'ModerationReport', id, creator_id, 'create', created_at
|
||||
FROM moderation_reports
|
||||
UNION ALL
|
||||
SELECT 'NoteVersion', id, updater_id, 'create', created_at
|
||||
FROM note_versions
|
||||
UNION ALL
|
||||
SELECT 'Post', id, uploader_id, 'create', created_at
|
||||
FROM posts
|
||||
UNION ALL
|
||||
SELECT 'PostAppeal', id, creator_id, 'create', created_at
|
||||
FROM post_appeals
|
||||
UNION ALL
|
||||
SELECT 'PostApproval', id, user_id, 'create', created_at
|
||||
FROM post_approvals
|
||||
UNION ALL
|
||||
SELECT 'PostDisapproval', id, user_id, 'create', created_at
|
||||
FROM post_disapprovals
|
||||
UNION ALL
|
||||
SELECT 'PostFlag', id, creator_id, 'create', created_at
|
||||
FROM post_flags
|
||||
UNION ALL
|
||||
SELECT 'PostReplacement', id, creator_id, 'create', created_at
|
||||
FROM post_replacements
|
||||
UNION ALL
|
||||
SELECT 'PostVote', id, user_id, 'create', created_at
|
||||
FROM post_votes
|
||||
UNION ALL
|
||||
SELECT 'SavedSearch', id, user_id, 'create', created_at
|
||||
FROM saved_searches
|
||||
UNION ALL
|
||||
SELECT 'TagAlias', id, creator_id, 'create', created_at
|
||||
FROM tag_aliases
|
||||
UNION ALL
|
||||
SELECT 'TagImplication', id, creator_id, 'create', created_at
|
||||
FROM tag_implications
|
||||
UNION ALL (
|
||||
SELECT 'TagVersion', id, updater_id, 'create', created_at
|
||||
FROM tag_versions
|
||||
WHERE updater_id IS NOT NULL
|
||||
ORDER BY created_at DESC
|
||||
) UNION ALL
|
||||
SELECT 'Upload', id, uploader_id, 'create', created_at
|
||||
FROM uploads
|
||||
UNION ALL
|
||||
SELECT 'User', id, id, 'create', created_at
|
||||
FROM users
|
||||
UNION ALL
|
||||
SELECT 'UserEvent', id, user_id, 'create', created_at
|
||||
FROM user_events
|
||||
UNION ALL
|
||||
SELECT 'UserFeedback', id, creator_id, 'create', created_at
|
||||
FROM user_feedback
|
||||
UNION ALL
|
||||
SELECT 'UserFeedback', id, user_id, 'subject', created_at
|
||||
FROM user_feedback
|
||||
UNION ALL (
|
||||
SELECT 'UserUpgrade', id, purchaser_id, 'create', created_at
|
||||
FROM user_upgrades
|
||||
WHERE status IN (20, 30)
|
||||
ORDER BY created_at DESC
|
||||
) UNION ALL
|
||||
SELECT 'UserNameChangeRequest', id, user_id, 'create', created_at
|
||||
FROM user_name_change_requests
|
||||
UNION ALL
|
||||
SELECT 'WikiPageVersion', id, updater_id, 'create', created_at
|
||||
FROM wiki_page_versions
|
||||
Reference in New Issue
Block a user