Ускорение многостоловых Mysql запросов, использующих Group By и Order By - PullRequest
0 голосов
/ 10 февраля 2020

Я пытаюсь ускорить запрос Mysql, работающий на Mysql 5.7. Эта таблица сейчас насчитывает около 9 миллионов записей (постоянно растет). У меня есть строгая структура базы данных, которая не допускает объединений (проверка на будущее для масштабирования). В настоящее время для запуска на моей локальной машине требуется 250-450 миллисекунд. Я не уверен, насколько это действительно может быть ускорено, но я должен попробовать.

Из моей оценки кажется, что подзапрос - это медленная часть, за которой следуют GROUP BY и ORDER BY.

Вот структура таблицы:

CREATE TABLE `image_has_posts` (
  `image_id` int(9) unsigned NOT NULL,
  `post_id` bigint(20) unsigned NOT NULL,
  `sequence` int(11) unsigned NOT NULL,
  PRIMARY KEY (`image_id`,`post_id`),
  KEY `index_on_timestamp` (`sequence`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE `post_has_privacy` (
  `post_id` bigint(20) unsigned NOT NULL,
  `is_private` tinyint(1) unsigned NOT NULL,
  `sequence` int(11) unsigned NOT NULL,
  PRIMARY KEY (`post_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Вот некоторые примеры данных для этой таблицы:

image_id  post_id       sequence
7264      44568969088   1033459621
8564      112520730415  1033459642
9205      44568969087   1033459645

Вот запрос. Предложение where in будет содержать от 200 до 1000 записей:

SELECT sql_no_cache 
post_id, image_id
FROM image_has_posts
WHERE image_id IN (40334, 48848, 8993, 32740, 39664, 5701, 53308, 1001, 1230, 24732, 12341, 25777, 94, 56560, 31853, 17884, 16591, 38522, 29450, 31360, 12025, 17799, 17488, 4917, 23317, 9488, 65885, 65175, 16027, 32138, 32056, 56434, 2009, 30706, 36260, 28985, 793, 17146, 22163, 25433, 65046, 56517, 3008, 34893, 34867, 69689, 31359, 19366, 3338, 29484, 49566, 70479, 6415, 19287, 812, 12677, 27023, 17275, 22072, 13930, 25153, 43221, 35516, 14346, 6514, 28791, 21220, 39667, 24438, 3486, 76252, 26890, 30905, 3579, 69546, 4674, 19159, 21693, 36639, 1687, 65678, 9250, 34009, 36514, 13014, 41571, 6454, 35857, 9804, 66333, 16500, 38051, 16759, 39944, 27128, 49703, 33347, 22720, 69, 17515, 5385, 14000, 8418, 6317, 1397, 7340, 3159, 31581, 311, 30628, 9919, 24229, 39407, 33572, 69327, 28745, 32309, 2334, 3988, 13243, 53287, 16034, 29050, 12818, 76190, 2463, 18207, 703, 15259, 31352, 8006, 14117, 44806, 22717, 24661, 15841, 6754, 32885, 9628, 7107, 17055, 49515, 66406, 902, 16878, 14841, 10932, 23521, 8825, 17754, 2118, 36839, 53234, 39556, 9363, 32840, 37663, 9482, 24228, 66371, 49603, 29614, 12066, 37190, 12389, 28775, 7200, 7187, 29489, 28055, 75902, 36348, 25535, 15696, 75929, 10172, 7186, 5218, 66118, 65368, 15337, 2601, 23819, 10870, 24120, 4165, 23426, 4109, 17581, 5102, 23911, 7263, 15024, 31357, 7193, 25665, 8691, 3791, 35934, 11423, 10726, 7595, 9381, 17267, 15641, 16628, 56870, 25617, 66436, 12370, 27873, 9514, 59397, 26807, 64879, 11301, 22795, 29274, 29007, 13281, 27985, 34630, 30844, 40127, 66254, 56886, 27887, 23623, 30851, 23897, 11672, 11501, 41153, 31660, 37927, 6710, 44566, 9817, 39110, 65886, 186, 15385, 3505, 17610, 14921, 10637, 39014, 15465, 26810, 38099, 41191, 32935, 30285, 16141, 3023, 65250, 12749, 35098, 13147, 9023, 2122, 23429, 3021, 76154, 26742, 25972, 32634, 13064, 27888, 14852, 36641, 44748, 71024, 16317, 5595, 38677, 26287, 10207, 44775, 3622, 81212, 36746, 26102, 40813, 6899, 26804, 15877, 37341, 4651, 25380, 14577, 35871, 35949, 65008, 31365, 41919, 49225, 28698, 26809, 31247, 38699, 1396, 41829, 19649, 27187, 22574, 1364, 41778, 41566, 13701, 28834, 15020, 38823, 40614, 25784, 42763, 42157, 27781, 23250, 6605, 29485, 12680, 64775, 65739, 40799, 52682, 59714, 31386, 21267, 32744, 49656, 66499, 26811, 20988, 774, 8700, 20814, 22, 30850, 70768, 33291, 41575, 41574, 9426, 17970, 2207, 4439, 8510, 21706, 45143, 9555, 1767, 7675, 22973, 66500, 30849, 13467, 9328, 45070, 11635, 69420, 44723, 13772, 56571, 7463, 13390, 25025, 21714, 35243, 35276, 59499, 2641, 13475, 316, 2108, 56952, 19032, 26660, 8824, 6391, 76073, 11639, 42127, 2799, 19693, 5196, 69396, 15916, 23509, 39905, 15732, 33013, 66074, 64867, 25349, 2110, 27165, 7945, 28077, 24737, 325, 26806, 3734, 30551, 26286, 18329, 34149, 33497, 18464, 59133, 17617, 49488, 32079, 42818, 20172, 44550, 17286, 35515, 4859, 37661, 24157, 17225, 38128, 16375, 3593, 35868, 41307, 38511, 59500, 27361, 6971, 65555, 2754, 42787, 24049, 69397, 7642, 1232, 23418, 24551, 56319, 11033, 49089, 13267, 22694, 41972, 8186, 19066, 1617, 39920, 26417, 3227, 37793, 11637, 24835, 9620, 19956, 8885, 5658, 11817, 31351, 2355, 37612, 16894, 39570, 15946, 11480, 32961, 3837)
    AND post_id IN (
        SELECT post_id 
        FROM post_has_privacy 
        WHERE is_private = 0
    )
GROUP BY image_id 
ORDER BY sequence DESC;                     

Вот оператор EXPLAIN:

{
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "9480.52"
    },
    "ordering_operation": {
      "using_temporary_table": true,
      "using_filesort": true,
      "grouping_operation": {
        "using_filesort": false,
        "nested_loop": [
          {
            "table": {
              "table_name": "image_has_posts",
              "access_type": "range",
              "possible_keys": [
                "PRIMARY",
                "index_on_timestamp"
              ],
              "key": "PRIMARY",
              "used_key_parts": [
                "image_id"
              ],
              "key_length": "4",
              "rows_examined_per_scan": 5628,
              "rows_produced_per_join": 5628,
              "filtered": "100.00",
              "cost_info": {
                "read_cost": "1601.32",
                "eval_cost": "1125.60",
                "prefix_cost": "2726.92",
                "data_read_per_join": "131K"
              },
              "used_columns": [
                "image_id",
                "post_id",
                "sequence"
              ],
              "attached_condition": "(`db`.`image_has_posts`.`image_id` in (40334,48848,8993,32740,39664,5701,53308,1001,1230,24732,12341,25777,94,56560,31853,17884,16591,38522,29450,31360,12025,17799,17488,4917,23317,9488,65885,65175,16027,32138,32056,56434,2009,30706,36260,28985,793,17146,22163,25433,65046,56517,3008,34893,34867,69689,31359,19366,3338,29484,49566,70479,6415,19287,812,12677,27023,17275,22072,13930,25153,43221,35516,14346,6514,28791,21220,39667,24438,3486,76252,26890,30905,3579,69546,4674,19159,21693,36639,1687,65678,9250,34009,36514,13014,41571,6454,35857,9804,66333,16500,38051,16759,39944,27128,49703,33347,22720,69,17515,5385,14000,8418,6317,1397,7340,3159,31581,311,30628,9919,24229,39407,33572,69327,28745,32309,2334,3988,13243,53287,16034,29050,12818,76190,2463,18207,703,15259,31352,8006,14117,44806,22717,24661,15841,6754,32885,9628,7107,17055,49515,66406,902,16878,14841,10932,23521,8825,17754,2118,36839,53234,39556,9363,32840,37663,9482,24228,66371,49603,29614,12066,37190,12389,28775,7200,7187,29489,28055,75902,36348,25535,15696,75929,10172,7186,5218,66118,65368,15337,2601,23819,10870,24120,4165,23426,4109,17581,5102,23911,7263,15024,31357,7193,25665,8691,3791,35934,11423,10726,7595,9381,17267,15641,16628,56870,25617,66436,12370,27873,9514,59397,26807,64879,11301,22795,29274,29007,13281,27985,34630,30844,40127,66254,56886,27887,23623,30851,23897,11672,11501,41153,31660,37927,6710,44566,9817,39110,65886,186,15385,3505,17610,14921,10637,39014,15465,26810,38099,41191,32935,30285,16141,3023,65250,12749,35098,13147,9023,2122,23429,3021,76154,26742,25972,32634,13064,27888,14852,36641,44748,71024,16317,5595,38677,26287,10207,44775,3622,81212,36746,26102,40813,6899,26804,15877,37341,4651,25380,14577,35871,35949,65008,31365,41919,49225,28698,26809,31247,38699,1396,41829,19649,27187,22574,1364,41778,41566,13701,28834,15020,38823,40614,25784,42763,42157,27781,23250,6605,29485,12680,64775,65739,40799,52682,59714,31386,21267,32744,49656,66499,26811,20988,774,8700,20814,22,30850,70768,33291,41575,41574,9426,17970,2207,4439,8510,21706,45143,9555,1767,7675,22973,66500,30849,13467,9328,45070,11635,69420,44723,13772,56571,7463,13390,25025,21714,35243,35276,59499,2641,13475,316,2108,56952,19032,26660,8824,6391,76073,11639,42127,2799,19693,5196,69396,15916,23509,39905,15732,33013,66074,64867,25349,2110,27165,7945,28077,24737,325,26806,3734,30551,26286,18329,34149,33497,18464,59133,17617,49488,32079,42818,20172,44550,17286,35515,4859,37661,24157,17225,38128,16375,3593,35868,41307,38511,59500,27361,6971,65555,2754,42787,24049,69397,7642,1232,23418,24551,56319,11033,49089,13267,22694,41972,8186,19066,1617,39920,26417,3227,37793,11637,24835,9620,19956,8885,5658,11817,31351,2355,37612,16894,39570,15946,11480,32961,3837))"
            }
          },
          {
            "table": {
              "table_name": "post_has_privacy",
              "access_type": "eq_ref",
              "possible_keys": [
                "PRIMARY"
              ],
              "key": "PRIMARY",
              "used_key_parts": [
                "post_id"
              ],
              "key_length": "8",
              "ref": [
                "db.image_has_posts.post_id"
              ],
              "rows_examined_per_scan": 1,
              "rows_produced_per_join": 562,
              "filtered": "10.00",
              "cost_info": {
                "read_cost": "5628.00",
                "eval_cost": "112.56",
                "prefix_cost": "9480.52",
                "data_read_per_join": "8K"
              },
              "used_columns": [
                "post_id",
                "is_private"
              ],
              "attached_condition": "(`db`.`post_has_privacy`.`is_private` = 0)"
            }
          }
        ]
      }
    }
  }
}

1 Ответ

1 голос
/ 10 февраля 2020

строгая структура базы данных, не допускающая объединений (проверка на будущее для масштабирования).

Я должен с этим не согласиться.

  • Во многих ситуациях IN ( SELECT ... ) работает хуже, чем эквивалент JOIN.

  • Я только что доказал в другой ситуации, что EXISTS ( SELECT ... ) был медленнее, чем эквивалент JOIN.

  • У «производных таблиц» есть свои проблемы.

  • Денормализация - это один из способов избежать JOINs, но это также может привести к непредвиденным проблемам с производительностью.

  • Извлечение идентификаторов одним SELECT и извлечение полезная информация со секундой SELECT почти гарантированно займет больше времени - в два раза больше, чем одна SELECT с JOIN. Это связано с накладными расходами каждого оператора SQL.

Я не говорю, что какие-либо аспекты анти-JOIN текущего запроса являются ошибочными. Пожалуйста, укажите EXPLAIN FORMAT=JSON SELECT ... для текущего запроса. Из EXPLAIN мы можем определить, сколько нужно сортировок, и насколько подзапрос настолько плох, насколько я боюсь.

Что делает этот запрос медленным, это

  • GROUP BY одно, потом ORDER BY что-то другое. Это заставляет хотя бы одну сортировку, возможно, две.
  • Что будет делать клиент с количеством выводимых строк более 1000?
  • Что будет со строками; клиент поворачивается и выбирает ссылки на изображения? Или Paginate?
  • Отображение один-ко-многим не должно использовать дополнительную таблицу, а должно проявляться через указатель на одну таблицу на другую.

Подробнее .. .

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * '' * '' * '' * '' ''. только (большой) кусок таблицы.

Пожалуйста, попробуйте другую форму объяснения: EXPLAIN FORMAT=JSON SELECT ...

Пожалуйста, предоставьте запрос, который предоставил идентификаторы и запрос, который будет использовать результирующие идентификаторы. Давайте попробуем создать один запрос, который выполняет все 3 шага, и посмотрим, насколько быстро он выполняется.

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