[英]Optimize this query further? - indexed but still slow
我在下面有一個查詢加入4個表。 我添加了索引,並且使用索引的解釋輸出看起來很好(見下文)。
我可以進一步優化查詢嗎?
modelXml在某些記錄上相當大。對於一個大型項目,我得到22條記錄,每條記錄大約有2.5-3MB的modelXml數據,查詢需要很長時間(總返回69MB的數據)。 我懷疑這是問題,但不知道如何處理它。 我正在閱讀調整內部mysql變量,例如key_buffer_size和table_cache。 這有什么幫助嗎?
key_buffer_size目前設置為8384512(~8MB),table_cache設置為64我應該將它增加到什么? 我應該考慮哪些其他變量來加速返回這些大數據?
歡迎任何其他建議。 我是mysql的新手,但我真的想要變得更好。
SELECT `m`.`modelId`, `m`.`modelTypeId`, `m`.`modelXml`, `m`.`xmlSize`, `m`.`createdById`, `m`.`creationDate`, `m`.`modifiedDate`, `u`.`firstName`, `u`.`lastName` FROM `models_1` AS `m`
INNER JOIN `modelFolderAssociations_1` AS `mfa` ON m.modelId = mfa.modelIOId
INNER JOIN `modelFolders_1` AS `mf` ON mfa.folderId = mf.folderId
INNER JOIN `users_1` AS `u` ON m.createdById = u.userId
WHERE (m.projectId = 2) AND (mfa.folderId = 5) AND (mfa.modelIOType = 2) AND (m.modelTypeId = 2)
CREATE TABLE `models` (
`modelId` int(11) NOT NULL auto_increment,
`customerId` int(11) NOT NULL,
`groupId` int(11) NOT NULL,
`projectId` int(11) NOT NULL,
`createdById` int(11) NOT NULL,
`modelTypeId` int(11) NOT NULL,
`modelXml` longtext,
`modelSpecXml` longtext NOT NULL,
`xmlSize` bigint(20) NOT NULL default '0',
`creationDate` datetime NOT NULL,
`modifiedDate` datetime NOT NULL,
PRIMARY KEY (`modelId`,`customerId`)
) ENGINE=InnoDB AUTO_INCREMENT=75 DEFAULT CHARSET=utf8
CREATE TABLE `modelFolders` (
`folderId` int(11) NOT NULL auto_increment,
`customerId` int(11) NOT NULL,
`groupId` int(11) NOT NULL,
`projectId` int(11) NOT NULL,
`parentId` int(11) NOT NULL,
`folderName` varchar(64) NOT NULL,
`folderType` int(11) NOT NULL,
`editable` tinyint(1) NOT NULL default '1',
`nextDefaultNameNumber` int(11) NOT NULL default '1',
`creationDate` datetime NOT NULL,
`modifiedDate` datetime NOT NULL,
PRIMARY KEY (`folderId`,`customerId`),
KEY `parentId` (`parentId`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8
CREATE TABLE `modelFolderAssociations` (
`associationId` int(11) NOT NULL auto_increment,
`customerId` int(11) NOT NULL,
`folderId` int(11) NOT NULL,
`projectId` int(11) NOT NULL,
`modelIOId` int(11) NOT NULL,
`modelIOType` tinyint(1) NOT NULL default '1',
`creationDate` datetime NOT NULL,
`modifiedDate` datetime NOT NULL,
PRIMARY KEY (`associationId`,`customerId`),
KEY `folderId` (`folderId`,`modelIOType`)
) ENGINE=InnoDB AUTO_INCREMENT=75 DEFAULT CHARSET=utf8
CREATE TABLE `users` (
`userId` int(11) NOT NULL auto_increment,
`customerId` int(11) NOT NULL,
`userName` varchar(50) NOT NULL,
`password` varchar(256) NOT NULL,
`firstName` varchar(50) default NULL,
`lastName` varchar(50) default NULL,
`creationDate` datetime NOT NULL,
`modifiedDate` datetime NOT NULL,
PRIMARY KEY (`userId`,`customerId`),
UNIQUE KEY `userName` (`userName`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8
解釋輸出
+----+-------------+-------------------------+--------+---------------+----------+---------+---------------------------------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------------------+--------+---------------+----------+---------+---------------------------------------------------+------+-------------+
| 1 | SIMPLE | modelFolders | const | PRIMARY | PRIMARY | 8 | const,const | 1 | Using index |
| 1 | SIMPLE | modelFolderAssociations | ref | folderId | folderId | 5 | const,const | 22 | Using where |
| 1 | SIMPLE | models | eq_ref | PRIMARY | PRIMARY | 8 | xa_system.modelFolderAssociations.modelIOId,const | 1 | Using where |
| 1 | SIMPLE | users | eq_ref | PRIMARY | PRIMARY | 8 | xa_system.models.createdById,const | 1 | |
+----+-------------+-------------------------+--------+---------------+----------+---------+---------------------------------------------------+------+-------------+
擁有大型文本列,就像您用來存儲我所假設的XML那樣,無論索引的結構如何,都會損害性能。
在這些情況下,可以更好地將文本列移動到單獨的表中,並按照您已經存儲的字符串長度和CRC32進行索引。
CREATE TABLE MODEL_XML (
xmlId INT(11) unsigned NOT NULL auto_increment,
xmlSize BIGINT(20) NOT NULL default '0',
crc32 INT(11) unsigned NOT NULL,
xmlData LONGTEXT,
PRIMARY KEY (xmlId),
UNIQUE KEY (xmlSize, crc32)
)
然后,表格中具有重要索引的列的寬度將保持不變。
恩。
modelXmlId INT(11) unsigned NOT NULL
specXmlId INT(11) unsigned NOT NULL
它還具有冗余文本(空字符串等)更節省空間的優點,因為它們將共享一個xmlId,因此在DB中共享一行。
您應該索引外鍵,這對您的連接有幫助:
CREATE INDEX IDX_MODELS_CUSTID
on models (customerId)
CREATE INDEX IDX_FLDR_ASSOC_MODELIO
modelFolderAssociations(modelIOId)
CREATE INDEX IDX_FLDR_ASSOC_FLDRID
modelFolderAssociations(folderId)
等等。
從SELECT子句中取出modelXml列后測試查詢。
如果速度明顯更好,則緩慢來自要傳輸的數據量,而不是查詢本身。
您的索引並不總是與查詢和聯接匹配。 如果WHERE和JOIN子句中的所有列都不在索引中,則會強制mysql查看基礎行,這將導致性能下降,尤其是因為模型行太寬。
對於“modelFolderAssociations”,您為where子句創建了正確的復合鍵,但是您應該為要建模的連接包含modelIOId。
對於“模型”,您需要(modelId,projectId,modelTypeId,createdById)上的復合索引來覆蓋來自mfa的傳入鏈接,where子句中的兩個項以及指向用戶的出站鏈接。
對於“modelFolders”和“users”,您可以在主鍵中包含傳入聯接。
引擎只會使用一個索引,因此添加額外的索引單個索引(如Mike所建議的)將不會那么好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.