优化此慢查询

时间:2019-06-02 07:24:46

标签: php mysql mariadb

请帮帮我,解决这个缓慢的查询

表格:

    CREATE TABLE `products` (
      `ProductId` int(11) NOT NULL AUTO_INCREMENT,
      `CategoryId` int(11) NOT NULL,
      `BrandId` int(11) DEFAULT NULL,
      `PCode` varchar(100) COLLATE utf8_persian_ci NOT NULL,
      `PName` varchar(255) COLLATE utf8_persian_ci NOT NULL,
      `UnitId` int(11) DEFAULT NULL,
      `PNameEn` varchar(250) COLLATE utf8_persian_ci DEFAULT NULL,
      `PShortName` varchar(100) COLLATE utf8_persian_ci DEFAULT NULL,
      `PDescription` varchar(250) COLLATE utf8_persian_ci DEFAULT NULL,
      `Weight` int(11) DEFAULT NULL,
      `PImage` varchar(100) COLLATE utf8_persian_ci NOT NULL DEFAULT 'noimage.png',
      `PIcon` varchar(100) COLLATE utf8_persian_ci DEFAULT 'noicon.png',
      `PGallery` varchar(250) COLLATE utf8_persian_ci DEFAULT NULL,
      `PDetail` text COLLATE utf8_persian_ci,
      `PTags` text COLLATE utf8_persian_ci,
      `PSpecial` tinyint(4) NOT NULL DEFAULT '0',
      `PView` int(11) NOT NULL DEFAULT '0',
      `Status` tinyint(2) DEFAULT '1' COMMENT '0: inactive. 1: active. 5: deleted.',
      `BasePrice` int(11) DEFAULT NULL,
      `PCreateDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
      `PUpdateDate` datetime NOT NULL,
      `PUrl` varchar(255) COLLATE utf8_persian_ci DEFAULT NULL,
      `ProviderName` varchar(255) COLLATE utf8_persian_ci DEFAULT NULL,
      PRIMARY KEY (`ProductId`),
      UNIQUE KEY `PCode` (`PCode`),
      KEY `CategoryId` (`CategoryId`),
      KEY `BrandId` (`BrandId`),
      KEY `PName` (`PName`)
    ) ENGINE=MyISAM AUTO_INCREMENT=341028 DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci

    CREATE TABLE `units` (
      `UnitId` int(11) NOT NULL AUTO_INCREMENT,
      `UnitName` varchar(25) COLLATE utf8_persian_ci NOT NULL,
      PRIMARY KEY (`UnitId`)
    ) ENGINE=MyISAM AUTO_INCREMENT=22 DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci

CREATE TABLE `products_sub` (
  `ProductSubId` int(11) NOT NULL AUTO_INCREMENT,
  `ProviderId` int(11) NOT NULL,
  `PCode` varchar(100) COLLATE utf8_persian_ci NOT NULL,
  `Price` int(11) NOT NULL,
  `ProviderPrice` int(11) NOT NULL,
  `PQuantity` int(10) NOT NULL,
  `PDeliveryTime` time NOT NULL,
  `PEditTime` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`ProductSubId`),
  KEY `ProviderId` (`ProviderId`),
  KEY `PCode` (`PCode`)
) ENGINE=MyISAM AUTO_INCREMENT=340349 DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci

CREATE TABLE `provider` (
  `ProviderId` int(11) NOT NULL AUTO_INCREMENT,
  `UserId` int(11) NOT NULL,
  `ProviderName` varchar(25) COLLATE utf8_persian_ci NOT NULL,
  `ProviderPhone` varchar(11) COLLATE utf8_persian_ci NOT NULL,
  `ProviderCell` varchar(11) COLLATE utf8_persian_ci NOT NULL,
  `ProviderAddress` varchar(250) COLLATE utf8_persian_ci NOT NULL,
  `ProviderDetail` text COLLATE utf8_persian_ci NOT NULL,
  `Email` varchar(50) COLLATE utf8_persian_ci NOT NULL,
  `Status` tinyint(1) NOT NULL,
  `RequestTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `Permission` varchar(250) COLLATE utf8_persian_ci NOT NULL,
  PRIMARY KEY (`ProviderId`),
  UNIQUE KEY `UserId` (`UserId`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci

CREATE TABLE `order_products` (
  `OrderProductId` int(11) NOT NULL AUTO_INCREMENT,
  `OrderId` int(11) NOT NULL,
  `ProviderId` int(11) NOT NULL,
  `PCode` varchar(50) COLLATE utf8_persian_ci NOT NULL,
  `PName` varchar(50) COLLATE utf8_persian_ci NOT NULL,
  `PUnit` varchar(50) COLLATE utf8_persian_ci NOT NULL,
  `Token` int(11) NOT NULL DEFAULT '999',
  `ProductPrice` int(11) NOT NULL,
  `ProductWeight` int(11) NOT NULL,
  `ProductPurchase` int(11) NOT NULL,
  PRIMARY KEY (`OrderProductId`),
  KEY `ProductId` (`PCode`),
  KEY `OrderId` (`OrderId`),
  KEY `ProviderId` (`ProviderId`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci

CREATE TABLE `brands` (
  `BrandId` int(11) NOT NULL AUTO_INCREMENT,
  `BrandName` varchar(25) NOT NULL,
  `BrandEn` varchar(25) DEFAULT NULL,
  PRIMARY KEY (`BrandId`),
  UNIQUE KEY `BrandName` (`BrandName`)
) ENGINE=MyISAM AUTO_INCREMENT=1988 DEFAULT CHARSET=utf8

我的查询

SELECT
            `products`.`ProductId`,
            `products`.`PName`,
            `products`.`Status`,
            `products`.`PSpecial`,
            `products`.`PImage`,
            `products`.`BasePrice`,
            `products`.`CategoryId`,
            `units`.`UnitName`,
            `products_sub`.`ProductSubId`,
            `products_sub`.`ProviderId`,
            `products_sub`.`PQuantity`,
            `products_sub`.`ProviderPrice`,
            `products_sub`.`Price` AS `customerPrice`,
            `provider`.`ProviderName`,
            SUM(`order_products`.`ProductPurchase`) AS `sale`
        FROM
            `products`
        LEFT JOIN
            `brands`
        ON
           `products`.`BrandId`=`brands`.`BrandId`
        INNER JOIN
            `units`
        ON
            `products`.`UnitId`=`units`.`UnitId`
        LEFT JOIN
            `products_sub`
        ON
            `products`.`PCode`=`products_sub`.`PCode`
        AND
            `products_sub`.`ProductSubId` = 
            (
                SELECT
                    `ProductSubId`
                FROM
                    `products_sub`
                WHERE
                    `PCode`=`products`.`PCode`
                AND
                    `PQuantity` > 0
                ORDER BY
                    `ProviderPrice`
                LIMIT
                    1
            )
        LEFT JOIN
            `provider`
        ON
            `products_sub`.`ProviderId`=`provider`.`ProviderId`
        LEFT JOIN
            `order_products`
        ON
            `products`.`PCode`=`order_products`.`PCode`
        WHERE
            `products`.`Status`>0
        AND
            `products`.`Status`!=5
        AND
            `products`.`CategoryId` IN (1133,1134,1137,1174,1175,1176,1138,1177,1178,1179,1139,1140,1141,1180,1181,1182,1183,1184,1142,1143,1144,1145,1185,1186,1187,1188,1189,1190,1191,1146,1147,1148,1149,1150,1192,1193,1194,1855,1856,1857,1135,1151,1152,1153,1154,1155,1156,1157,1158,1136,1159,1160,1161,1162,1163,1164,1165,1166,1195,1196,1197,1198,1199,1167,1168,1200,1201,1202,1203,1204,1205,1169,1206,1207,1208,1209,1170,1171,1172,1173,1210,1211,1858,1859,1212,1213,1214,1232,1233,1234,1215,1216,1235,1236,1237,1238,1217,1239,1240,1241,1242,1218,1219,1220,1243,1244,1245,1246,1247,1248,1221,1249,1250,1251,1222,1223,1224,1252,1253,1254,1225,1255,1256,1257,1258,1259,1260,1261,1262,1263,1226,1227,1228,1229,1230,1231,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1463,1464,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1465,1466,1467,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1468,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1469,1470,1471,1472,1473,1474,1508,1509,1286,1287,1290,1299,1395,1396,1300,1301,1397,1398,1399,1302,1303,1304,1305,1400,1401,1402,1306,1307,1308,1309,1403,1404,1310,1405,1406,1407,1408,1311,1312,1313,1314,1315,1409,1410,1291,1316,1317,1318,1319,1320,1292,1321,1322,1323,1324,1288,1293,1325,1411,1412,1326,1327,1413,1414,1328,1329,1330,1331,1415,1416,1417,1418,1332,1419,1420,1421,1422,1333,1334,1335,1423,1424,1336,1425,1426,1427,1428,1429,1430,1431,1337,1338,1432,1433,1434,1339,1340,1341,1342,1435,1436,1437,1343,1438,1439,1440,1441,1294,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1295,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1860,1861,1862,1289,1296,1364,1442,1443,1444,1365,1445,1446,1447,1448,1366,1367,1368,1369,1449,1450,1451,1452,1453,1370,1371,1372,1373,1454,1455,1456,1457,1458,1459,1374,1375,1460,1376,1377,1378,1379,1461,1462,1297,1380,1381,1382,1383,1384,1385,1386,1298,1387,1388,1389,1390,1391,1392,1393,1394,1863,1864,1865,1132)
        GROUP BY
            `products`.`PCode`
        ORDER BY
            `products`.`Status`,
            `products_sub`.`PQuantity` > 0 DESC,
            `products`.`PSpecial` DESC,
            `customerPrice` ASC,
            `products`.`BasePrice` ASC
        LIMIT
            36
        OFFSET
            0

此查询非常慢:(

当删除ORDER BY部分时,它将运行非常快。

根据我的研究,最好使用子查询。但没有弄清楚如何在左联接中使用它们。

感谢您的帮助。谢谢。

2 个答案:

答案 0 :(得分:0)

FWIW,我将以这种方式编写该查询。我不能说它将对性能产生任何显着影响,但是如果您提供相同的EXPLAIN,那么我们可以着眼于改善索引...

SELECT p.productid
     , p.pname
     , p.status
     , p.pspecial
     , p.pimage
     , p.baseprice
     , p.categoryid
     , u.unitname
     , s.productsubid
     , s.providerid
     , s.pquantity
     , s.providerprice
     , s.price customerprice
     , r.providername
     , SUM(op.productpurchase) sale
  FROM products p
  JOIN units u
    ON u.unitid = p.unitid
  LEFT 
  JOIN products_sub s
    ON s.pcode = p.pcode
  JOIN 
     ( SELECT productsubid
            , pcode
            , MIN(providerprice) providerprice
         FROM products_sub 
        WHERE pquantity = 0
        GROUP
           BY productsubid
            , pcode
      ) x
     ON x.productsubid = s.productsubid
    AND x.pcode = p.pcode
    AND x.providerprice = s.provideprice
   LEFT 
   JOIN provider r
     ON r.providerid = s.providerid
   LEFT 
   JOIN order_products op
     ON op.pcode = p.pcode
  WHERE p.status > 0
    AND p.status != 5
    AND p.categoryid in 
      ( 1133 , 1134 , 1137 , 1174 , 1175 , 1176 , 1138 , 1177 , 1178 , 1179 , 1139 , 1140 , 1141 , 1180 , 1181 , 1182 , 1183 , 1184 , 1142 , 1143
      , 1144 , 1145 , 1185 , 1186 , 1187 , 1188 , 1189 , 1190 , 1191 , 1146 , 1147 , 1148 , 1149 , 1150 , 1192 , 1193 , 1194 , 1855 , 1856 , 1857
      , 1135 , 1151 , 1152 , 1153 , 1154 , 1155 , 1156 , 1157 , 1158 , 1136 , 1159 , 1160 , 1161 , 1162 , 1163 , 1164 , 1165 , 1166 , 1195 , 1196 
      , 1197 , 1198 , 1199 , 1167 , 1168 , 1200 , 1201 , 1202 , 1203 , 1204 , 1205 , 1169 , 1206 , 1207 , 1208 , 1209 , 1170 , 1171 , 1172 , 1173 
      , 1210 , 1211 , 1858 , 1859 , 1212 , 1213 , 1214 , 1232 , 1233 , 1234 , 1215 , 1216 , 1235 , 1236 , 1237 , 1238 , 1217 , 1239 , 1240 , 1241
      , 1242 , 1218 , 1219 , 1220 , 1243 , 1244 , 1245 , 1246 , 1247 , 1248 , 1221 , 1249 , 1250 , 1251 , 1222 , 1223 , 1224 , 1252 , 1253 , 1254
      , 1225 , 1255 , 1256 , 1257 , 1258 , 1259 , 1260 , 1261 , 1262 , 1263 , 1226 , 1227 , 1228 , 1229 , 1230 , 1231 , 1264 , 1265 , 1266 , 1267
      , 1268 , 1269 , 1270 , 1271 , 1272 , 1273 , 1274 , 1275 , 1276 , 1277 , 1278 , 1279 , 1280 , 1281 , 1282 , 1283 , 1284 , 1285 , 1463 , 1464
      , 1475 , 1476 , 1477 , 1478 , 1479 , 1480 , 1481 , 1482 , 1483 , 1484 , 1465 , 1466 , 1467 , 1485 , 1486 , 1487 , 1488 , 1489 , 1490 , 1491
      , 1492 , 1493 , 1494 , 1468 , 1495 , 1496 , 1497 , 1498 , 1499 , 1500 , 1501 , 1502 , 1503 , 1504 , 1505 , 1506 , 1507 , 1469 , 1470 , 1471 
      , 1472 , 1473 , 1474 , 1508 , 1509 , 1286 , 1287 , 1290 , 1299 , 1395 , 1396 , 1300 , 1301 , 1397 , 1398 , 1399 , 1302 , 1303 , 1304 , 1305
      , 1400 , 1401 , 1402 , 1306 , 1307 , 1308 , 1309 , 1403 , 1404 , 1310 , 1405 , 1406 , 1407 , 1408 , 1311 , 1312 , 1313 , 1314 , 1315 , 1409 
      , 1410 , 1291 , 1316 , 1317 , 1318 , 1319 , 1320 , 1292 , 1321 , 1322 , 1323 , 1324 , 1288 , 1293 , 1325 , 1411 , 1412 , 1326 , 1327 , 1413
      , 1414 , 1328 , 1329 , 1330 , 1331 , 1415 , 1416 , 1417 , 1418 , 1332 , 1419 , 1420 , 1421 , 1422 , 1333 , 1334 , 1335 , 1423 , 1424 , 1336
      , 1425 , 1426 , 1427 , 1428 , 1429 , 1430 , 1431 , 1337 , 1338 , 1432 , 1433 , 1434 , 1339 , 1340 , 1341 , 1342 , 1435 , 1436 , 1437 , 1343 
      , 1438 , 1439 , 1440 , 1441 , 1294 , 1344 , 1345 , 1346 , 1347 , 1348 , 1349 , 1350 , 1351 , 1352 , 1353 , 1295 , 1354 , 1355 , 1356 , 1357 
      , 1358 , 1359 , 1360 , 1361 , 1362 , 1363 , 1860 , 1861 , 1862 , 1289 , 1296 , 1364 , 1442 , 1443 , 1444 , 1365 , 1445 , 1446 , 1447 , 1448
      , 1366 , 1367 , 1368 , 1369 , 1449 , 1450 , 1451 , 1452 , 1453 , 1370 , 1371 , 1372 , 1373 , 1454 , 1455 , 1456 , 1457 , 1458 , 1459 , 1374
      , 1375 , 1460 , 1376 , 1377 , 1378 , 1379 , 1461 , 1462 , 1297 , 1380 , 1381 , 1382 , 1383 , 1384 , 1385 , 1386 , 1298 , 1387 , 1388 , 1389 
      , 1390 , 1391 , 1392 , 1393 , 1394 , 1863 , 1864 , 1865 , 1132
      )
  GROUP 
     BY p.productid
      , p.pname
      , p.status
      , p.pspecial
      , p.pimage
      , p.baseprice
      , p.categoryid
      , u.unitname
      , s.productsubid
      , s.providerid
      , s.pquantity
      , s.providerprice
      , s.price
      , r.providername
  ORDER 
     BY p.status
      , s.pquantity > 0 desc
      , p.pspecial desc
      , customerpprice asc
      , p.baseprice asc
  LIMIT 36
 OFFSET 0

答案 1 :(得分:0)

这将大大加快一个子查询的速度:INDEX(PCode, PQuantity, ProviderPrice)。添加时,您也可以摆脱KEY PCode (PCode)

从MyISAM切换到InnoDB。

基于对status的评论

           `products`.`Status`>0
      AND  `products`.`Status`!=5

可以简单地变成products.Status = 1。这样做的原因是使某些优化成为可能。特别是,这将变得有用:

INDEX(Status, CategoryId)