@skyone

Как оптимизировать sql запрос?

Как можно оптимизировать такой запрос?

SELECT `api_list`.*, CONCAT_WS('-', `api_list`.`key`, `api_list`.`sc`, `api_list`.`t1`, `bases`.`update_id`) as assigned_id, `bases`.`update_id`, `updates`.`name`, SUM(`api_list`.`qty`) as sum, `updates_prices`.`price`, (`updates_prices`.`price` * 0.93) as discounted_price 
FROM `api_list` 
JOIN `bases` ON (`bases`.`base_id` = `api_list`.`base_id` AND `bases`.`api_id` = `api_list`.`api_id`) 
JOIN `updates_prices` ON (`updates_prices`.`price_id` = CONCAT(`api_list`.`key`, `api_list`.`sc`, `bases`.`update_id`)) 
JOIN `updates` ON (`updates`.`id` = `bases`.`update_id`) 
WHERE `bases`.`update_id` IN (686, 685, 684, 683, 682, 681, 679, 678, 677, 671, 670, 669, 668, 667, 666, 665, 664, 663, 662, 661, 660, 659, 658, 657, 656, 655, 654, 653, 652, 651, 650, 649, 648, 647, 645, 643, 642, 641, 640, 639, 638, 637, 636, 635, 634, 633, 632, 631, 630, 629, 628, 627, 626, 625, 624, 623, 622, 619, 618, 617, 616, 615, 614, 613, 611, 610, 609, 608, 607, 606, 605, 604, 603, 602, 601, 600, 599, 598, 597, 596, 595, 594, 593, 592, 591, 590, 589, 588, 587, 586, 585, 584, 583, 582, 581, 580, 579, 578, 577, 576, 575, 574, 573, 572, 571, 570, 569, 568, 567, 566, 565, 564, 563, 562, 561, 560, 559, 558, 557, 556, 555, 554, 553, 552, 551, 550, 549, 548, 547, 546, 545, 544, 543, 542, 541, 540, 539, 538, 537, 536, 535, 534, 533, 532, 531, 530, 529, 528, 527, 526, 525, 524, 523, 522, 521, 520, 519, 518, 517, 516, 514, 513, 512, 511, 510, 509, 508, 507, 506, 505, 504, 503, 502, 501, 500, 499, 498, 497, 496, 495, 494, 493, 492, 491, 490, 489, 488, 487, 486, 485, 484, 483, 482, 481, 480, 479, 478, 477, 476, 475, 473, 472, 471, 470, 469, 468, 467, 465, 464, 463, 462, 461, 460, 459, 458, 457, 456, 455, 454, 453, 452, 451, 450, 449, 448, 447, 446, 445, 444, 443, 442, 441, 440, 438, 437, 436, 435, 434, 433, 432, 431, 430, 429, 428, 427, 426, 425, 424, 423, 422, 421, 420, 419, 418, 417, 416, 414, 413, 412, 411, 410, 409, 408, 407, 406, 404, 403, 402, 401, 400, 399, 398, 397, 396, 395, 394, 393, 392, 377, 374, 372, 371, 370, 369, 368, 367, 348, 347, 346, 345, 344, 343, 340, 336, 335, 334, 333, 332, 331, 330, 329, 322, 321, 316, 315, 314, 313, 311, 310, 309, 304, 303, 299, 298, 297, 295, 293, 291, 290, 289, 288, 287, 286, 285, 281, 280, 279, 278, 277, 276, 266, 265, 264, 258, 257, 255, 253, 252, 251, 250, 249, 248, 247, 246, 245, 239, 238, 237, 236, 235, 207, 165) 
AND `api_list`.`is_removed` = 0 
GROUP BY `bases`.`update_id`, `api_list`.`key`, `api_list`.`sc`, `api_list`.`t1` 
ORDER BY `updates`.`id` DESC 
LIMIT 100 
OFFSET 0


запрос выполняется 13 сек, в таблице api_list 360к записей, вот explain

b6791898a7fc4881a6eaceb55a5d59ea.png
  • Вопрос задан
  • 176 просмотров
Пригласить эксперта
Ответы на вопрос 2
alexey-m-ukolov
@alexey-m-ukolov Куратор тега MySQL
Самый первый шаг выполняется вообще без индекса, ещё и с файловой сортировкой.
Добавьте в bases индекс по update_id и посмотрите что получится. В теории, это должно улучшить ситуацию, но оптимизация запросов - это наполовину теория, а на половину пробы и ошибки.

Если это не поможет, то, по-хорошему, нужно разбивать ваш запрос на несколько простых и выполнять аггрегацию и подсчёты в коде, это часто бывает оптимальнее одного гигантского запроса.
Ответ написан
kimono
@kimono
Web developer
Колбаса из WHERE x IN(.....) жесть.
Вообще, сложные и намудреные запросы нельзя писать сразу целиком. Сделайте простой запрос с JOINом, гляньте какие индексы используются, потом добавьте условия WHERE, затем группировку, сортировку. На каждом этапе при добавлении условий легче будет отследить - "стало лучше или хуже" в плане использования индексов.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы