對於我的mysql-audit-tables project我想比較原始數據表的定義和相關的審計表,它具有相同的列和一些標題信息。連接到子查詢的選擇查詢永遠運行
編輯:針對此問題創造一個sqlfiddle後,我發現在sqlfiddle(MYSQL V5.6)它是工作,在我的5.7安裝在Windows上我有3個查詢的第三個不同的結果(丟棄列)。
編輯:
CREATE TABLE `audit_testdata`.`testtable` (-- the data table!
`text_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`text_type_id` bigint(20) unsigned NOT NULL,
`text_other_id` bigint(20) unsigned NOT NULL,
`text_lng_id` bigint(20) unsigned NOT NULL,
`text_access_id` bigint(20) DEFAULT NULL,
`text_html` text,
`text_plain` text,
`testadd` varchar(42) DEFAULT NULL,-- new field to test queries!
PRIMARY KEY (`text_id`),
UNIQUE KEY `text_id` (`text_id`)
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8;
CREATE TABLE `audit`.`testtable_audit` (-- audit table, simplified
`audit_seq` bigint(20) unsigned NOT NULL,
`audit_pk` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`audit_timestamp` timestamp NOT NULL,
`text_id` bigint(20) unsigned NOT NULL COMMENT 'pk_testtable: ',-- change d field to test queries.
`text_type_id` bigint(20) unsigned NOT NULL,
`text_other_id` bigint(20) unsigned NOT NULL,
`text_lng_id` bigint(20) unsigned NOT NULL,
`text_access_id` bigint(20) DEFAULT NULL,
`text_html` text,
`text_plain` text,
`text_symbol` blob,-- deleted field to test queries.
PRIMARY KEY (`audit_pk`),
UNIQUE KEY `audit_pk` (`audit_pk`),
KEY `text_id` (`text_id`),
KEY `audit_timestamp` (`audit_timestamp`),
KEY `audit_seq` (`audit_seq`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
一些製備的觀點::添加了例如表爲比較
DROP VIEW IF EXISTS v_audit_info_tables;
CREATE VIEW v_audit_info_tables AS
SELECT CONCAT('`',TABLE_SCHEMA,'`.`',TABLE_NAME,'`') AS FQ_TABLE_NAME,
TABLE_SCHEMA,TABLE_NAME
FROM information_schema.TABLES;
DROP VIEW IF EXISTS v_audit_info_columns;
CREATE VIEW v_audit_info_columns AS
SELECT CONCAT('`',TABLE_SCHEMA,'`.`',TABLE_NAME,'`') AS FQ_TABLE_NAME,
CONCAT('`',TABLE_SCHEMA,'`.`',TABLE_NAME,'`.`',COLUMN_NAME,'`') AS FQ_COLUMN_NAME,
TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME,COLUMN_TYPE,IS_NULLABLE,COLUMN_KEY,COLUMN_DEFAULT,
CONCAT('`',COLUMN_NAME,'` ',
UPPER(COLUMN_TYPE),
IF(IS_NULLABLE='YES',' NULL ',' NOT NULL '),
'COMMENT ''',REPLACE(COLUMN_COMMENT,'''',''''''),'''') AS FQ_COLUMN_CHANGE
FROM information_schema.COLUMNS;
這裏是一個映射視圖到每個數據表與它審計錶鏈接。在我真正的項目有配置表的使用方法:
DROP VIEW IF EXISTS v_audit_map_tables;
CREATE VIEW v_audit_map_tables AS
SELECT dat.FQ_TABLE_NAME AS dat_fq_table_name,dat.TABLE_SCHEMA AS dat_table_schema,dat.TABLE_NAME AS dat_table_name,
aud.FQ_TABLE_NAME AS aud_fq_table_name,aud.TABLE_SCHEMA AS aud_table_schema,aud.TABLE_NAME as aud_table_name
FROM v_audit_info_tables dat JOIN v_audit_info_tables aud
ON aud.TABLE_NAME = CONCAT(dat.TABLE_NAME,'_audit')
WHERE dat.TABLE_SCHEMA = 'audit_testdata' AND aud.TABLE_SCHEMA = 'audit';
;
對於一個完整的畫面在這裏修改列工作查詢:
SELECT dat.FQ_COLUMN_NAME,dat.FQ_COLUMN_CHANGE,AUD.FQ_COLUMN_CHANGE,
CONCAT('ALTER TABLE ',aud.FQ_TABLE_NAME,' MODIFY COLUMN `',dat.COLUMN_NAME,'` ',dat.FQ_COLUMN_CHANGE) AS modify_cmd,
dat.FQ_TABLE_NAME,aud.FQ_TABLE_NAME
FROM v_audit_info_columns dat JOIN v_audit_info_columns aud
ON dat.COLUMN_NAME = aud.COLUMN_NAME
WHERE dat.FQ_COLUMN_CHANGE <> aud.FQ_COLUMN_CHANGE
;
這裏非工作查詢,這似乎永遠運行:
SELECT dat.FQ_COLUMN_NAME,dat.FQ_COLUMN_CHANGE,NULL,
CONCAT('ALTER TABLE ',audmap.aud_fq_table_name,' ADD COLUMN `',dat.COLUMN_NAME,'` ',dat.FQ_COLUMN_CHANGE) AS modify_cmd,
dat.FQ_TABLE_NAME,audmap.aud_fq_table_name
FROM v_audit_info_columns dat JOIN v_audit_map_tables audmap
ON audmap.dat_fq_table_name = dat.FQ_TABLE_NAME
WHERE dat.COLUMN_NAME NOT IN
(SELECT DISTINCT aud.COLUMN_NAME FROM v_audit_info_columns aud
WHERE aud.TABLE_NAME = audmap.aud_table_name AND aud.TABLE_SCHEMA = audmap.aud_table_schema
-- AND aud.FQ_TABLE_NAME = audmap.aud_fq_table_name
);
我第一次嘗試了aud.FQ_TABLE_NAME = audmap.aud_fq_table_name
和直接ADRESS的TABLE_NAME/TABLE_SCHEMA
。我看了很多其他問題,所以我的新想法是重新設計最終查詢,但我仍然不知道,如何。
EDIT-2:現在這裏是緩慢的工作解決方案,上面的查詢是緩慢的和錯誤的。讓它工作的重要提示是在MYSQL documentation。我把案件集中在一個UNION,這在我的Windows運行約6秒,所以我仍然有興趣,優化更多:
SELECT dat.FQ_COLUMN_NAME,dat.FQ_COLUMN_CHANGE AS dat_change,AUD.FQ_COLUMN_CHANGE AS aud_change,
CONCAT('ALTER TABLE ',aud.FQ_TABLE_NAME,' MODIFY COLUMN `',dat.COLUMN_NAME,'` ',dat.FQ_COLUMN_CHANGE) AS modify_cmd,
dat.FQ_TABLE_NAME AS dat_table_name,aud.FQ_TABLE_NAME AS aud_table_name
FROM v_audit_info_columns dat JOIN v_audit_info_columns aud
ON dat.COLUMN_NAME = aud.COLUMN_NAME
JOIN v_audit_map_tables audmap
ON dat.FQ_TABLE_NAME = audmap.dat_fq_table_name AND aud.FQ_TABLE_NAME = audmap.aud_fq_table_name
WHERE dat.FQ_COLUMN_CHANGE <> aud.FQ_COLUMN_CHANGE
UNION
SELECT dat.FQ_COLUMN_NAME,dat.FQ_COLUMN_CHANGE,NULL,
CONCAT('ALTER TABLE ',audmap.aud_fq_table_name,' ADD COLUMN `',dat.COLUMN_NAME,'` ',dat.FQ_COLUMN_CHANGE) AS modify_cmd,
dat.FQ_TABLE_NAME,audmap.aud_fq_table_name
FROM v_audit_info_columns dat
JOIN v_audit_map_tables audmap ON (audmap.dat_fq_table_name = dat.FQ_TABLE_NAME)
WHERE NOT EXISTS (SELECT 1 FROM v_audit_info_columns aud WHERE dat.aud_fq_column_name = aud.FQ_COLUMN_NAME)
UNION
SELECT aud.FQ_COLUMN_NAME,NULL,aud.FQ_COLUMN_CHANGE,
CONCAT('-- ALTER TABLE ',aud.FQ_TABLE_NAME,' DROP COLUMN `',aud.COLUMN_NAME,'`') AS modify_cmd,
audmap.dat_fq_table_name, audmap.aud_fq_table_name
FROM v_audit_info_columns aud JOIN v_audit_map_tables audmap
ON audmap.aud_fq_table_name = aud.FQ_TABLE_NAME
WHERE NOT EXISTS (SELECT 1 FROM v_audit_info_columns dat
WHERE dat.fq_column_name = CONCAT(audmap.dat_fq_table_name,'.`',aud.COLUMN_NAME,'`'))
;
我已經添加了'WHERE TABLE_SCHEMA IN('audit','audit_testdata');'對於前三個視圖,它將最終查詢增強到了2.5秒。此外,我使用新的'FQ_COLUMN_NAME'在子查詢中進行搜索,如果將子查詢限制爲指定的表,則2.5中還會有0.016。我仍然對更好的解決方案感興趣,因爲我的測試環境2.5沒問題,但是對於多個表,我預計執行時間會更長...... – Myonara