2014-04-18 31 views
0

我正在使用MySql 5.5.37。我試圖從一組表中截斷數據。我讀到這裏 - Quickest way to delete enormous MySQL table,即重新創建/重命名錶是假想快,但我得到的錯誤...什麼是截斷MySQL中一組表的更快方法?

SET FOREIGN_KEY_CHECKS=0; 
… 
CREATE TABLE IF NOT EXISTS new_organization LIKE organization; 
RENAME TABLE organization TO old_t, new_organization TO organization; 
DROP TABLE old_t; 

CREATE TABLE IF NOT EXISTS new_organization_address LIKE organization_address; 
RENAME TABLE organization_address TO old_t, new_organization_address TO organization_address; 

ERROR 1025 (HY000): Error on rename of './sbjunit_ebook/organization_address' to './sbjunit_ebook/old_t' (errno: 150) 

進一步展望問題,它說...

Error in foreign key constraint of table sbjunit_ebook/old_t: 
there is no index in referenced table which would contain 
the columns as the first columns, or the data types in the 
referenced table do not match the ones in table. Constraint: 
, 
    CONSTRAINT "FK1_ORGANIZTION_ADDRESS" FOREIGN KEY ("ORGANIZATION_ID") REFERENCES "old_t" ("ID") ON DELETE CASCADE ON UPDATE NO ACTION 
The index in the foreign key in table is "UK_ORGANIZATION_ADDRESS" 

爲什麼重命名不更新外鍵引用的表以及什麼是從一組表中截斷數據的更快方法?

回答

0

重命名錶(使用RENAME TABLE語句)不會影響引用表的外鍵。引用表的外鍵僅在它們不受影響的意義上得到「更新」,它們不會「丟失」。只有表格名稱會受到影響;引用表的外鍵引用不會丟失。

當您禁用foreign_key_checks時,您實質上是在告訴數據庫您承擔了維護數據完整性的責任。它不會指示MySQL在重命名錶時重新定義外鍵約束定義。

在這種情況下,當被丟棄命名old_t表,MySQL假設一個名爲old_t表將被重新創建,而且將有一個合適的索引(列名,列數據類型),現有的外鍵將引用。它還假設將插入適當的行,以便滿足所有外鍵約束。

(注意DROP TABLE聲明不會成功,如果FOREIGN_KEY_CHECKS啓用,該語句會返回一個錯誤。)


清空該表實際上是禁用的外鍵的最快方法引用該表的約束,然後在該表上執行TRUNCATE語句。 MySQL實際上會通過創建一個新的空表執行TRUNCATE操作(在下面),然後刪除舊的表。

您可以按照其他表格的相同模式。

此時,您將重新啓用外鍵約束。

(MySQL不支持真正禁用/啓用的外鍵約束,我們必須下降及補充外鍵約束

ALTER TABLE bar DROP 
FOREIGN KEY (foo_id) ; 

ALTER TABLE bar ADD 
    CONSTRAINT FK_bar_foo 
    FOREIGN KEY (foo_id) REFERENCES foo (id) ; 

(請注意,創建的「大」表的外鍵約束。可需要一些時間,但如果表bar是空的,這將是非常快。)


UPDATE

可以查詢information_schema表以幫助構建外鍵的DROPADD

在刪除現有的外鍵約束之前,「保存」它是很重要的。

此SQL語句適用於在我的某些表上生成外鍵約束DROPADD的語句。 (我所有的外鍵約束具有用戶提供的名字,沒有系統生成的名稱。)您的里程可能會有所不同:

外鍵引用mydatabase.mytable

SELECT CONCAT('ALTER TABLE `',r.constraint_schema,'`.`',r.table_name 
      ,'` ADD' 
      ,' CONSTRAINT `',r.constraint_name,'`' 
      ,' FOREIGN KEY (' 
      ,GROUP_CONCAT(CONCAT('`',k.column_name,'`') 
          ORDER BY k.ordinal_position) 
      ,') REFERENCES ',r.referenced_table_name 
      ,' (' 
      ,GROUP_CONCAT(CONCAT('`',k.referenced_column_name,'`') 
          ORDER BY k.ordinal_position) 
      ,')' 
      ,' ON UPDATE ',r.update_rule 
      ,' ON DELETE ',r.delete_rule 
      ,';' 
     ) AS add_fk 
    , CONCAT('ALTER TABLE `',r.constraint_schema,'`.`',r.table_name 
       ,'` DROP FOREIGN KEY ' 
       ,'`',r.constraint_name,'`' 
       ,';' 
     ) AS drop_fk 
    FROM information_schema.referential_constraints r 
    JOIN information_schema.key_column_usage k 
     ON k.constraint_schema = r.constraint_schema 
     AND k.table_name = r.table_name 
     AND k.constraint_name = r.constraint_name 
WHERE r.constraint_schema = 'mydatabase' 
    AND r.referenced_table_name = 'mytable' 
GROUP BY r.constraint_schema, r.table_name, r.constraint_name ; 
+0

我想看看有沒有更好的除了說「truncate table t」之外,還有一種方法可以截斷表,但是在你的回答中,你是否真的使用了「truncate」語句來清除數據?我誤解你的建議嗎? – Dave

+0

@Dave:是的,如果沒有引用表的外鍵約束,則TRUNCATE是最快的。當沒有外鍵約束時,它相當於刪除現有表並創建一個新的空表。 – spencer7593

+0

聽起來不錯。我的截斷所有表的腳本是自動生成的,因此我需要找出一種方法來刪除並重新創建外鍵。然後我可以針對我現在的情況進行速度測試,然後我會回來接受。 – Dave

相關問題