@s_ha_dum suggests that Post meta will be deleted automatically. Therefore because his reputation suggests he knows what he is talking about, this solution only handles Post attachments.
I'd suggest checking out the docs for the before_delete_post() hook, as it's quite handy to be able to check out what Post Type is being deleted, etc.
if($post_type !== 'my_custom_post_type') return;
$args = array(
'post_type' => 'attachment',
'post_status' => 'any',
'posts_per_page' => -1,
'post_parent' => $post_id
$attachments = new WP_Query($args);
$attachment_ids = array();
if($attachments->have_posts()) : while($attachments->have_posts()) : $attachments->the_post();
$attachment_ids = get_the_id();
$delete_attachments_query = $wpdb->prepare('DELETE FROM %1$s WHERE %1$s.ID IN (%2$s)', $wpdb->posts, join(',', $attachment_ids));
An important note from the aforementioned docs -
It's important to note the hook runs only when the WordPress user empties the Trash. If you using this hook note that it will not fire if the user is deleting an Attachment, since attachments are force deleted, i.e., not sent to the Trash. Instead use the delete_post() hook.
I should mention that while the code in this answer will delete all rows from the database related to Post attachments, it will not actually delete the attachments themselves.
My reasoning for this is performance. Depending on the number of attachments that you have, deleting them one at a time could take a while. I suggest it is better to to only delete the database entries for all attachments initially to enhance the user experience, and then run some separate house keeping at another time to delete the actual attachments (it's easy enough to search for and delete and non-associated files). Basically, less queries + less work during the user experience = less time.