簡體   English   中英

使用mysql 5.7使用NULL IS NULL OR條件語法進行慢速查詢

[英]Slow query with NULL IS NULL OR condition syntax using Mysql 5.7

我從運行“簡單”查詢的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 OR條件)對我來說非常方便,以便使我的代碼更緊湊,並且無需根據參數數量創建其他查詢。

對於誰了解Hibernate HQL和JPA的工作原理,請執行以下查詢:

在此處輸入圖片說明

當用戶未設置任何過濾器時將生成此查詢,因此我的條件下的所有參數均為null,這就是查詢的結果。

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)

該查詢在137548行的表上花費約0.105s 上一個查詢的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 or condition”

我認為Ryan是正確的,因此many或語句使查詢變得如此糟糕。

您應該以編程方式構建查詢以提高性能。 因此,如果用戶未按可能的過濾器進行選擇,則不應將其包括在查詢中!

(HQL)

if(!StringUtils.isEmpty(manufacturer)) {
  query.and(m.manufacturer.eq(manufacturer))
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM