[英]mysql innodb inner join with longtext very slow
我上周將一個項目的所有MySQL表從MyISAM遷移到InnoDB,以支持交易。 為此,我使用了alter table
的命令。
大多數工作正常,但是一個特定的查詢運行速度非常慢,它總是Incorrect key file for table '/tmp/#sql_xxxx_x.MYI
提供錯誤Incorrect key file for table '/tmp/#sql_xxxx_x.MYI
后來我將問題縮小到2個表的內連接,即user
表和agreement
表。 而內部聯接采取的外鍵字段之間發生user
(即agreement_id
)和主鍵字段agreement
(即id
)。
user
表只有50,000行數據, agreement
表也有一行。 我們已經為用戶的agreement_id
設置了索引。
無論如何,這似乎是一個非常輕量級的查詢,但事實證明它是整個瓶頸。
這是完整的agreement
架構:
CREATE TABLE IF NOT EXISTS `agreement` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`remark` varchar(200) NOT NULL,
`content` longtext NOT NULL,
`is_active` tinyint(1) NOT NULL,
`date_stamp` datetime NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
我懷疑的一件事是agreement
表中的remark
的longtext字段,但我們沒有使用該字段進行內連接,實際上即使我們沒有在查詢結果中選擇remark
,查詢也很慢。
最后,我們將agreement
表從innoDB
回MyISAM
,而不是一切正常。 查詢在不到1秒的時間內完成。
現在,我的問題是這里究竟發生了什么? 這是否意味着一旦innoDB表包含任何文本字段,那么該表不能用於內連接?
我希望我能夠知道真正的原因,以便我將來可以避免同樣的問題。
非常感謝。
這是一個着名而棘手的問題。 最可能的原因是你在/ tmp中沒有空間。
這是我在書簽中保留的鏈接,可以幫助您: http : //www.mysqlperformancetuning.com/a-fix-for-incorrect-key-file-for-table-mysql
根據我的經驗,盡管有限,但看到此錯誤消息的主要原因是因為您的tmpdir空間不足。 像我一樣,你會檢查你有多少可用空間:1Gb,2Gb,4Gb。 這可能還不夠。 這就是原因:MySQL可以在幾秒鍾內創建比這更大的臨時表,快速填滿任何可用空間。 具體取決於查詢的性質和數據庫的大小。
您也可以嘗試在桌面上使用REPAIR ,但對我而言,它與breakdancing一樣有用:/
InnoDB有自己的緩沖區大小等設置。檢查出來,如果你可以調整它,繼續。 只是為了測試嘗試加倍,如果它有幫助,你可能想要優化它。 它可以產生很大的不同。
一些可能有用的鏈接:
http://www.mysqlperformanceblog.com/2007/11/03/choosing-innodb_buffer_pool_size/
http://dev.mysql.com/doc/refman/5.5/en/innodb-buffer-pool.html
也許這里的問題是remark
字段定義為varchar(200)
? 請記住,臨時表和內存表存儲具有固定長度的varchar
。 所以帶有varchar(200)
50k行即使它們都是空的,也會占用大量內存。
如果這是問題,那么你可以嘗試以下幾種方法之一:
varchar(200)
列,並始終使用NULL值而不是空字符串 varchar(200)
更改為文本(當然有缺點 - 它將始終使用磁盤上的臨時表) VARCHAR
大小 您的查詢的目的是什么? 我從您的評論中看到,您只列出了用戶信息,而且協議中沒有任何內容讓我相信您正在尋找有協議的用戶? 由於您在引擎之間進行轉換,因此我會在添加約束之前認為您正在進行清理。 如果是這樣,請考慮使用用戶表中的左連接,如:
select user.* from user left join agreement on user.agreement_id = agreement.id where user.agreement_id != 0;
如果它不是清理,而只是尋找具有協議的用戶,我們就會變得簡單
select user.* from user where user.agreement_id != 0;
如果目的不是其他,請考慮在user.agreement_id上添加索引,因為內部聯接可能需要它來提高速度。 讓我們知道真正的目的,你可能會得到更好的幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.