Important legacy note: The SQL below matches a specific generation of the Hive metastore schema from around 2013. You should only apply it if you have confirmed that these tables and indexes are missing in your metastore and that the definitions match your Hive version. Always test on a non-production copy of your metastore first.
Symptom
When using PostgreSQL as the Hive metastore database, a statement like:
DROP TABLE xyz;
may hang indefinitely. On the PostgreSQL side, you see long-running transactions and locks with UPDATE operations on metastore tables, even though no obvious workload is active.
This can be caused by missing indexes and privilege tables that Hive expects to exist. Without them, metadata operations (including DROP TABLE) can block or fail.
DDL patch for missing Hive metastore tables and indexes (PostgreSQL)
The following SQL creates the missing indexes on IDXS and the privilege/role-related tables and indexes. Run it against your metastore database from the psql CLI, connected as the Hive metastore user.
-- Indexes on IDXS
CREATE INDEX "IDXS_FK1" ON "IDXS" USING btree ("SD_ID");
CREATE INDEX "IDXS_FK2" ON "IDXS" USING btree ("INDEX_TBL_ID");
CREATE INDEX "IDXS_FK3" ON "IDXS" USING btree ("ORIG_TBL_ID");
-- ROLES table
CREATE TABLE "ROLES" (
"ROLE_ID" bigint NOT NULL,
"CREATE_TIME" int NOT NULL,
"OWNER_NAME" varchar(128) DEFAULT NULL,
"ROLE_NAME" varchar(128) DEFAULT NULL,
PRIMARY KEY ("ROLE_ID"),
CONSTRAINT "ROLEENTITYINDEX" UNIQUE ("ROLE_NAME")
);
-- ROLE_MAP table
CREATE TABLE "ROLE_MAP" (
"ROLE_GRANT_ID" bigint NOT NULL,
"ADD_TIME" int NOT NULL,
"GRANT_OPTION" smallint NOT NULL,
"GRANTOR" varchar(128) DEFAULT NULL,
"GRANTOR_TYPE" varchar(128) DEFAULT NULL,
"PRINCIPAL_NAME" varchar(128) DEFAULT NULL,
"PRINCIPAL_TYPE" varchar(128) DEFAULT NULL,
"ROLE_ID" bigint DEFAULT NULL,
PRIMARY KEY ("ROLE_GRANT_ID"),
CONSTRAINT "USERROLEMAPINDEX"
UNIQUE ("PRINCIPAL_NAME","ROLE_ID","GRANTOR","GRANTOR_TYPE"),
CONSTRAINT "ROLE_MAP_FK1"
FOREIGN KEY ("ROLE_ID") REFERENCES "ROLES" ("ROLE_ID")
);
-- GLOBAL_PRIVS table
CREATE TABLE "GLOBAL_PRIVS" (
"USER_GRANT_ID" bigint NOT NULL,
"CREATE_TIME" int NOT NULL,
"GRANT_OPTION" smallint NOT NULL,
"GRANTOR" varchar(128) DEFAULT NULL,
"GRANTOR_TYPE" varchar(128) DEFAULT NULL,
"PRINCIPAL_NAME" varchar(128) DEFAULT NULL,
"PRINCIPAL_TYPE" varchar(128) DEFAULT NULL,
"USER_PRIV" varchar(128) DEFAULT NULL,
PRIMARY KEY ("USER_GRANT_ID"),
CONSTRAINT "GLOBALPRIVILEGEINDEX"
UNIQUE ("PRINCIPAL_NAME","PRINCIPAL_TYPE","USER_PRIV","GRANTOR","GRANTOR_TYPE")
);
-- DB_PRIVS table
CREATE TABLE "DB_PRIVS" (
"DB_GRANT_ID" bigint NOT NULL,
"CREATE_TIME" int NOT NULL,
"DB_ID" bigint DEFAULT NULL,
"GRANT_OPTION" smallint NOT NULL,
"GRANTOR" varchar(128) DEFAULT NULL,
"GRANTOR_TYPE" varchar(128) DEFAULT NULL,
"PRINCIPAL_NAME" varchar(128) DEFAULT NULL,
"PRINCIPAL_TYPE" varchar(128) DEFAULT NULL,
"DB_PRIV" varchar(128) DEFAULT NULL,
PRIMARY KEY ("DB_GRANT_ID"),
CONSTRAINT "DBPRIVILEGEINDEX"
UNIQUE ("DB_ID","PRINCIPAL_NAME","PRINCIPAL_TYPE",
"DB_PRIV","GRANTOR","GRANTOR_TYPE"),
CONSTRAINT "DB_PRIVS_FK1"
FOREIGN KEY ("DB_ID") REFERENCES "DBS" ("DB_ID")
);
-- PART_PRIVS table
CREATE TABLE "PART_PRIVS" (
"PART_GRANT_ID" bigint NOT NULL,
"CREATE_TIME" int NOT NULL,
"GRANT_OPTION" smallint NOT NULL,
"GRANTOR" varchar(128) DEFAULT NULL,
"GRANTOR_TYPE" varchar(128) DEFAULT NULL,
"PART_ID" bigint DEFAULT NULL,
"PRINCIPAL_NAME" varchar(128) DEFAULT NULL,
"PRINCIPAL_TYPE" varchar(128) DEFAULT NULL,
"PART_PRIV" varchar(128) DEFAULT NULL,
PRIMARY KEY ("PART_GRANT_ID"),
CONSTRAINT "PART_PRIVS_FK1"
FOREIGN KEY ("PART_ID") REFERENCES "PARTITIONS" ("PART_ID")
);
CREATE INDEX "PARTPRIVILEGEINDEX"
ON "PART_PRIVS"
USING btree ("PART_ID","PRINCIPAL_NAME","PRINCIPAL_TYPE",
"PART_PRIV","GRANTOR","GRANTOR_TYPE");
-- PART_COL_PRIVS table
CREATE TABLE "PART_COL_PRIVS" (
"PART_COLUMN_GRANT_ID" bigint NOT NULL,
"COLUMN_NAME" varchar(128) DEFAULT NULL,
"CREATE_TIME" int NOT NULL,
"GRANT_OPTION" smallint NOT NULL,
"GRANTOR" varchar(128) DEFAULT NULL,
"GRANTOR_TYPE" varchar(128) DEFAULT NULL,
"PART_ID" bigint DEFAULT NULL,
"PRINCIPAL_NAME" varchar(128) DEFAULT NULL,
"PRINCIPAL_TYPE" varchar(128) DEFAULT NULL,
"PART_COL_PRIV" varchar(128) DEFAULT NULL,
PRIMARY KEY ("PART_COLUMN_GRANT_ID"),
CONSTRAINT "PART_COL_PRIVS_FK1"
FOREIGN KEY ("PART_ID") REFERENCES "PARTITIONS" ("PART_ID")
);
CREATE INDEX "PARTITIONCOLUMNPRIVILEGEINDEX"
ON "PART_COL_PRIVS"
USING btree ("PART_ID","COLUMN_NAME","PRINCIPAL_NAME","PRINCIPAL_TYPE",
"PART_COL_PRIV","GRANTOR","GRANTOR_TYPE");
How to apply this in PostgreSQL
Connect to your Hive metastore database with psql and paste the DDL:
psql -h <HOSTNAME> -d metastore -U hiveuser -W
After the tables and indexes have been created successfully, retry:
DROP TABLE xyz;
In many legacy setups this resolves the hanging DROP TABLE issue because the metastore schema now matches what Hive expects and PostgreSQL can evaluate privilege and metadata queries efficiently instead of stalling on missing objects.
Reminder: Always dump and back up your metastore before running manual DDL like this, and validate that your Hive version expects these exact table and column names.
If you need help with distributed systems, backend engineering, or data platforms, check my Services.