Медленный запрос с NULL IS NULL ИЛИ синтаксис условия, используя Mysql 5.7 - PullRequest
0 голосов
/ 19 ноября 2018

Я получаю некоторые странные временные значения от Mysql, выполняющего «простой» запрос.

Это DDL таблицы:

CREATE TABLE `frame` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `createdBy` varchar(255) DEFAULT NULL,
  `createdDate` datetime(6) NOT NULL,
  `lastModifiedBy` varchar(255) DEFAULT NULL,
  `lastModifiedDate` datetime(6) DEFAULT NULL,
  `sid` varchar(36) NOT NULL,
  `version` bigint(20) NOT NULL,
  `brand` varchar(255) DEFAULT NULL,
  `category` varchar(255) DEFAULT NULL,
  `colorCode` varchar(255) DEFAULT NULL,
  `colorDescription` varchar(255) DEFAULT NULL,
  `description` longtext,
  `imageUrl` varchar(255) DEFAULT NULL,
  `lastPurchase` datetime(6) DEFAULT NULL,
  `lastPurchasePrice` decimal(19,2) DEFAULT NULL,
  `lastSell` datetime(6) DEFAULT NULL,
  `lastSellPrice` decimal(19,2) DEFAULT NULL,
  `line` varchar(255) DEFAULT NULL,
  `manufacturer` varchar(255) DEFAULT NULL,
  `manufacturerCode` varchar(255) DEFAULT NULL,
  `name` varchar(255) NOT NULL,
  `preset` bit(1) NOT NULL DEFAULT b'0',
  `purchasePrice` decimal(19,2) DEFAULT NULL,
  `salesPrice` decimal(19,2) DEFAULT NULL,
  `sku` varchar(255) NOT NULL,
  `stock` bit(1) NOT NULL DEFAULT b'1',
  `thumbUrl` varchar(255) DEFAULT NULL,
  `upc` varchar(255) DEFAULT NULL,
  `arm` int(11) DEFAULT NULL,
  `bridge` int(11) DEFAULT NULL,
  `caliber` int(11) DEFAULT NULL,
  `gender` varchar(255) DEFAULT NULL,
  `lensColor` varchar(255) DEFAULT NULL,
  `material` varchar(255) DEFAULT NULL,
  `model` varchar(255) NOT NULL,
  `sphere` decimal(10,2) DEFAULT NULL,
  `type` varchar(255) NOT NULL,
  `taxRate_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK_k7s4esovkoacsc264bcjrre13` (`sid`),
  UNIQUE KEY `UK_ajh6mr6a6qg6mgy8t9nevdym1` (`sku`),
  UNIQUE KEY `UK_boqikmg9o89j8q0o5ujkj33b3` (`upc`),
  KEY `idx_manufacturer` (`manufacturer`),
  KEY `idx_brand` (`brand`),
  KEY `idx_line` (`line`),
  KEY `idx_colorcode` (`colorCode`),
  KEY `idx_preset` (`preset`),
  KEY `idx_manufacturer_model_color_caliber` (`manufacturer`,`model`,`colorCode`,`caliber`),
  KEY `FK1nau29fd70s1nq905dgs6ft85` (`taxRate_id`),
  CONSTRAINT `FK1nau29fd70s1nq905dgs6ft85` FOREIGN KEY (`taxRate_id`) REFERENCES `taxrate` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=392179 DEFAULT CHARSET=utf8;

Запрос создается программно из моегоприложение.«Странный» синтаксис (условие NULL IS NULL ИЛИ) очень удобен для меня, чтобы сделать мой код более компактным и избавить от необходимости создавать другой запрос, основанный на количестве параметров.

Для тех, кто понимаеткак Hibernate HQL и JPA работает, это запрос:

enter image description here

Этот запрос генерируется, когда пользователь не устанавливает какой-либо фильтр, поэтому все параметры вмое условие пусто, и вот как получается запрос.

SELECT SQL_NO_CACHE COUNT(frame0_.`id`) AS col_0_0_ FROM `Frame` frame0_ 
WHERE (NULL IS NULL OR NULL LIKE CONCAT('%', NULL, '%') OR frame0_.`manufacturer` LIKE CONCAT('%', NULL, '%') OR frame0_.`manufacturerCode`=NULL OR frame0_.`sku`=NULL OR frame0_.`upc`=NULL OR frame0_.`line` LIKE CONCAT('%', NULL, '%') OR frame0_.`model` LIKE CONCAT('%', NULL, '%')) AND (NULL IS NULL OR frame0_.`manufacturer`=NULL) AND (NULL IS NULL OR frame0_.`line`=NULL) AND (NULL IS NULL OR frame0_.`caliber`=NULL) AND (NULL IS NULL OR frame0_.`type`=NULL) AND (NULL IS NULL OR frame0_.`material`=NULL) AND (NULL IS NULL OR frame0_.`model`=NULL) AND (NULL IS NULL OR frame0_.`colorCode`=NULL)

Запрос занимает около 0,105s для таблицы из 137548 строк.EXPLAIN предыдущего запроса возвращает:

id  select_type table   partitions  type    possible_keys   key key_len ref rows     filtered   Extra
1   SIMPLE       frame0_      \N             ALL    \    N  \N  \N  \N      137548   100.00   \N

Предыдущий запрос идентичен этому:

SELECT SQL_NO_CACHE COUNT(frame0_.`id`) AS col_0_0_ FROM `Frame` frame0_

Этот запрос занимает всего 0.05s для того же результата в той же таблице.

Почему для Mysql они разные и первое занимает так много времени?Есть ли способ повысить производительность первого запроса, сохранив синтаксис «NULL IS NULL или условие» ?

1 Ответ

0 голосов
/ 20 ноября 2018

Я думаю, что Райан имеет право, поэтому оператор many или сделал запрос настолько плохим.

Вам следует программно создавать запросы для повышения производительности.Так что если пользователь не выбрал возможный фильтр, то вам не следует включать в запрос!

(HQL)

if(!StringUtils.isEmpty(manufacturer)) {
  query.and(m.manufacturer.eq(manufacturer))
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...