Оптимизировать этот запрос дальше? - проиндексировано, но все еще медленно - PullRequest
3 голосов
/ 01 апреля 2011

У меня есть запрос ниже, который объединяет 4 таблицы.Я добавил индексы, и результат объяснения выглядит хорошо с использованными индексами (см. Ниже).

Могу ли я оптимизировать запрос дальше?

ModelXml довольно большой для некоторых записей. Для большого проекта, в котором я получаю 22 записи, каждая из которых содержит приблизительно 2,5–3 МБ данных modelXml, запрос занимает много времени (всего возвращается 69 МБ данных).Я подозреваю, что это проблема, но не знаю, как с ней бороться.Я читал о настройке внутренних переменных MySQL, например, key_buffer_size и table_cache.Поможет ли что-нибудь из этого?

key_buffer_size в настоящее время имеет значение 8384512 (~ 8 МБ), а 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 |             |
+----+-------------+-------------------------+--------+---------------+----------+---------+---------------------------------------------------+------+-------------+

Ответы [ 4 ]

1 голос
/ 02 апреля 2011

Наличие больших текстовых столбцов, таких как те, которые вы используете для хранения 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)
)

Тогда ширина ваших столбцов в таблице с вашими важными индексами станет постоянной.

ex.

modelXmlId INT(11) unsigned NOT NULL
specXmlId INT(11) unsigned NOT NULL

Преимущество такого подхода заключается в том, что он более экономит место для избыточного текста (пустых строк и т. Д.), Поскольку все они совместно используют один xmlId и, следовательно, одну строку в БД.

0 голосов
/ 01 апреля 2011

Проверьте ваш запрос после удаления столбца modelXml из предложения SELECT.

Если скорость значительно выше, то медлительность возникает из-за объема данных, передаваемых для передачи, а не из самого запроса.

0 голосов
/ 01 апреля 2011

Ваши индексы не всегда соответствуют запросам и объединениям.Если все столбцы в ваших предложениях WHERE и JOIN отсутствуют в индексе, вы заставляете mysql просматривать базовую строку, что снизит производительность, тем более что строки вашей модели очень широки.

Для "modelFolderAssociations" вы сделали правильный составной ключ для предложения where, но вы должны включить modelIOId для объединения с моделью.

Для "models" вы хотите составной индекс для (modelId, projectId, modelTypeId, creationById) для покрытия входящей ссылки из mfa, двух элементов в предложении where и исходящей ссылки на пользователей.

Для "modelFolders" и "users" входящее соединение покрывается вваши первичные ключи.

Движок будет использовать только один индекс, поэтому добавление дополнительных индексов для отдельных индексов (как предложил Майк) не будет таким хорошим.

0 голосов
/ 01 апреля 2011

Вы должны проиндексировать свои внешние ключи, это действительно поможет с вашими объединениями:

CREATE INDEX IDX_MODELS_CUSTID
on models (customerId)

CREATE INDEX IDX_FLDR_ASSOC_MODELIO
modelFolderAssociations(modelIOId)


CREATE INDEX IDX_FLDR_ASSOC_FLDRID
modelFolderAssociations(folderId)

и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...