MySQL слишком много объединений и строк - время выполнения - PullRequest
0 голосов
/ 04 апреля 2020

Я пытаюсь выполнить запрос, но слишком много соединений, следовательно, медленное время выполнения. Я смотрю на другие альтернативы, такие как PHP вместо mysql. Все еще ломаю голову над тем, сколько запросов / соединений мне нужно запустить. Любые предложения?

5 Таблицы и их ряды
2Вариант увеличивается на 5000 строк в год
ди увеличивается, может быть, на 100 000 в год
документ увеличивается на 50 000 в год
type и hashtag являются константами около 20

VARIABLES
Теперь вот что с моим запросом
$ groups = group by type ИЛИ group by hashtag ИЛИ оба
$ query_where = REGEXP, чтобы найти только определенный тип и / или хэштег из списка массива (выбранного пользователем), например, find_in_set

$query_where .=  "AND CONCAT(',', `type.product_type`, ',') REGEXP ',($types_arr),' ";

Запрос ниже выполняется около 38 секунд
Это только в том случае, если $ groups = type.product_type only
и
$ query_where = ""

        SELECT 
type.product_type as type, hashtag.variation_hashtag as hashtag,
di.warehouse, sum(di.qty)as qty, sum(di.price) as price, sum(di.sold_price) as sold_price, sum(di.cogs) as cogs, avg(di.price) as ave_price, avg(di.sold_price) as ave_sold_price, 
YEAR(docs.created_on) as year, MONTH(docs.created_on) as month
        FROM  2Variations v
            LEFT JOIN docs_inventory as di on di.product_id = v.product_id
            LEFT JOIN docs on docs.id = di.doc_id
            LEFT JOIN variations_type_link as type on v.id = type.id
            LEFT JOIN variations_hashtag_link as hashtag on v.id = hashtag.id
        WHERE
            di.deleted = 0 and
            type.deleted = 0 and
            (hashtag.deleted = 0 or hashtag.deleted is null) and 
            di.warehouse between 1 and 2
            ".$query_where."
        GROUP BY
            YEAR(docs.created_on), MONTH(docs.created_on), ".$groups;

EXPLAIN

+----+-------------+---------+--------+--------------------+------------+---------+-----------------------+------+----------------------------------------------+--+
| id | select_type |  table  |  type  |   possible_keys    |    key     | key_len |          ref          | rows |                    Extra                     |  |
+----+-------------+---------+--------+--------------------+------------+---------+-----------------------+------+----------------------------------------------+--+
|  1 | SIMPLE      | type    | ALL    | PRIMARY,deleted    | NULL       | NULL    | NULL                  | 4730 | Using where; Using temporary; Using filesort |  |
|  1 | SIMPLE      | v       | eq_ref | PRIMARY,product_id | PRIMARY    | 4       | database.type.id      |    1 | Using where                                  |  |
|  1 | SIMPLE      | hashtag | eq_ref | PRIMARY            | PRIMARY    | 4       | database.v.id         |    1 | Using where                                  |  |
|  1 | SIMPLE      | di      | ref    | product_id         | product_id | 4       | database.v.product_id |  218 | Using where                                  |  |
|  1 | SIMPLE      | docs    | eq_ref | PRIMARY            | PRIMARY    | 4       | database.di.doc_id    |    1 | NULL                                         |  |
+----+-------------+---------+--------+--------------------+------------+---------+-----------------------+------+----------------------------------------------+--+

ТАБЛИЦА СОЗДАНИЯ

Create Table
2Variations CREATE TABLE `2Variations` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `customer_id` int(11) NOT NULL,
 `auto_reorder` tinyint(1) NOT NULL DEFAULT '0',
 `product_id` int(11) NOT NULL,
 `qty_name` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 `color` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
 `supplier_code` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 `barcode` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 `upca` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 `no_pic` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
 `restock` int(11) NOT NULL DEFAULT '1',
 `hashtag` text COLLATE utf8mb4_unicode_ci,
 `php_wholesale` decimal(11,2) DEFAULT NULL,
 `php_retail` decimal(11,2) DEFAULT NULL,
 `weight` decimal(11,2) NOT NULL DEFAULT '0.00',
 `notes` text COLLATE utf8mb4_unicode_ci,
 `company_notes` text COLLATE utf8mb4_unicode_ci,
 `mgnt_notes` text COLLATE utf8mb4_unicode_ci,
 `deleted` int(11) NOT NULL DEFAULT '0',
 `retired` tinyint(4) NOT NULL DEFAULT '0',
 `created_by` int(20) NOT NULL,
 `created_on` datetime NOT NULL,
 `updated_by` int(20) NOT NULL,
 `last_update` datetime NOT NULL,
 PRIMARY KEY (`id`),
 KEY `product_id` (`product_id`),
 KEY `customer_id` (`customer_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5083 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci



docs    CREATE TABLE `docs` (
     `id` int(11) NOT NULL AUTO_INCREMENT,
     `customer_id` int(11) NOT NULL COMMENT 'id in table customers',
     `registered_id` int(20) NOT NULL DEFAULT '0',
     `doc_type` int(1) NOT NULL DEFAULT '0' COMMENT '0: none, 1:PO, 2:DR, 3:INV, 4: RS',
     `doc_no` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
     `doc_date` date NOT NULL,
     `duedate` date DEFAULT NULL,
     `confirm_date` date NOT NULL,
     `paid` date NOT NULL,
     `paid_amount` decimal(11,2) DEFAULT NULL,
     `sf` decimal(11,2) DEFAULT NULL,
     `rsf` decimal(11,2) DEFAULT NULL,
     `vat` decimal(11,2) DEFAULT NULL,
     `vatinex` int(1) DEFAULT NULL COMMENT '1 = in, 2 = ex',
     `merc_total` decimal(11,2) NOT NULL DEFAULT '0.00',
     `payment` decimal(11,2) NOT NULL DEFAULT '0.00',
     `commission` decimal(11,2) NOT NULL DEFAULT '0.00',
     `discount` decimal(11,2) DEFAULT '0.00',
     `voucher_amount` decimal(11,2) NOT NULL DEFAULT '0.00',
     `bundle_discount_amount` decimal(11,2) NOT NULL DEFAULT '0.00',
     `shipped` datetime DEFAULT NULL,
     `ext_courier` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
     `ext_courier_tracking` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
     `ext_orderid` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
     `ext_total_weight` decimal(11,4) NOT NULL,
     `notes` longtext COLLATE utf8mb4_unicode_ci,
     `company_notes` text COLLATE utf8mb4_unicode_ci,
     `mgnt_notes` longtext COLLATE utf8mb4_unicode_ci,
     `created_by` int(11) NOT NULL COMMENT 'id in users',
     `created_on` datetime NOT NULL,
     `updated_by` int(11) NOT NULL COMMENT 'id in users',
     `last_update` datetime NOT NULL,
     `deleted` int(11) NOT NULL DEFAULT '0',
     `deleted_reason` int(11) NOT NULL DEFAULT '0',
     PRIMARY KEY (`id`),
     KEY `doc_no` (`doc_no`),
     KEY `customer_id` (`customer_id`),
     KEY `ext_courier_tracking` (`ext_courier_tracking`,`ext_orderid`),
     KEY `ext_orderid` (`ext_orderid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=77904 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci



docs_inventory  CREATE TABLE `docs_inventory` (
     `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
     `doc_id` int(11) NOT NULL COMMENT 'id in table doc',
     `product_id` int(11) NOT NULL COMMENT 'id in table products',
     `color` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
     `qty` int(11) NOT NULL DEFAULT '0',
     `warehouse` int(11) NOT NULL DEFAULT '1',
     `price` decimal(11,2) NOT NULL DEFAULT '0.00',
     `sold_price` decimal(11,2) NOT NULL DEFAULT '0.00',
     `cogs` decimal(11,2) DEFAULT NULL,
     `deleted` int(11) NOT NULL DEFAULT '0',
     PRIMARY KEY (`id`),
     KEY `doc_id` (`doc_id`),
     KEY `product_id` (`product_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=395438 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci



products_type_link  CREATE TABLE `products_type_link` (
     `id` int(11) NOT NULL AUTO_INCREMENT,
     `product_id` int(20) NOT NULL,
     `product_type` int(20) NOT NULL,
     `created_by` int(20) NOT NULL,
     `created_on` datetime NOT NULL,
     `updated_by` int(20) NOT NULL,
     `last_update` datetime NOT NULL,
     `deleted` int(11) NOT NULL DEFAULT '0',
     PRIMARY KEY (`id`),
     KEY `product_type` (`product_type`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4088 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci



variations_hashtag_link CREATE TABLE `variations_hashtag_link` (
     `id` int(11) NOT NULL AUTO_INCREMENT,
     `variation_id` int(20) NOT NULL,
     `variation_hashtag` int(20) NOT NULL,
     `created_by` int(20) NOT NULL,
     `created_on` datetime NOT NULL,
     `updated_by` int(20) NOT NULL,
     `last_update` datetime NOT NULL,
     `deleted` int(11) NOT NULL DEFAULT '0',
     PRIMARY KEY (`id`),
     KEY `variation_hashtag` (`variation_hashtag`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3703 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

ОБНОВЛЕННЫЙ ИНДЕКС, чтобы включить Удаленный, стал медленнее до 45 сек

+----+-------------+---------+--------+------------------------------+------------+---------+------------------------+--------+----------------------------------------------+--+
| id | select_type |  table  |  type  |        possible_keys         |    key     | key_len |          ref           |  rows  |                    Extra                     |  |
+----+-------------+---------+--------+------------------------------+------------+---------+------------------------+--------+----------------------------------------------+--+
|  1 | SIMPLE      | di      | ref    | product_id,warehouse,deleted | deleted    |       4 | const                  | 169837 | Using where; Using temporary; Using filesort |  |
|  1 | SIMPLE      | docs    | eq_ref | PRIMARY                      | PRIMARY    |       4 | database.di.doc_id     |      1 | NULL                                         |  |
|  1 | SIMPLE      | v       | ref    | PRIMARY,product_id           | product_id |       4 | database.di.product_id |      2 | Using index                                  |  |
|  1 | SIMPLE      | hashtag | eq_ref | PRIMARY                      | PRIMARY    |       4 | database.v.id          |      1 | Using where                                  |  |
|  1 | SIMPLE      | type    | eq_ref | PRIMARY,deleted,deleted_2    | PRIMARY    |       4 | database.v.id          |      1 | Using where                                  |  |
+----+-------------+---------+--------+------------------------------+------------+---------+------------------------+--------+----------------------------------------------+--+

Ответы [ 3 ]

0 голосов
/ 04 апреля 2020

Другой альтернативный способ для массивных запросов - создание временной таблицы и заполнение ее с помощью SQL заданий. например, каждые 10 минут выполнять большой запрос, вставлять его во временную таблицу. Затем просто написать запрос для временной таблицы.

0 голосов
/ 04 апреля 2020

Не ответ; слишком долго для комментария ...

Прежде всего, чтобы помочь, нам действительно нужно увидеть полный запрос, и лично мне легче его читать при форматировании, например, следующим образом:

SELECT t.product_type type
     , h.variation_hashtag hashtag
     , di.warehouse
     , SUM(di.qty) qty
     , SUM(di.price) price
     , SUM(di.sold_price) sold_price
     , SUM(di.cogs) cogs
     , AVG(di.price) ave_price
     , AVG(di.sold_price) ave_sold_price
     , YEAR(d.created_on) year
     , MONTH(d.created_on) month
  FROM 2Variations v 
  JOIN docs_inventory di 
    ON di.product_id = v.product_id
  LEFT 
  JOIN docs d
    ON d.id = di.doc_id 
  JOIN variations_type_link t 
    ON t.id = v.id
  LEFT 
  JOIN variations_hashtag_link h
    ON h.id = v.id
 WHERE di.deleted = 0 
   AND t.deleted = 0 
   AND (h.deleted = 0 or h.deleted IS NULL)
   AND di.warehouse BETWEEN 1 AND 2
".$query_where."
 GROUP 
    BY YEAR(d.created_on)
     , MONTH(d.created_on)
     , ".$groups;

Обратите внимание, что я заменил пару ВНЕШНИХ СОЕДИНЕНИЙ на ВНУТРЕННИЕ СОЕДИНЕНИЯ, потому что они изначально не были НАРУЖНЫМИ СОЕДИНЕНИЯМИ. Кроме того, очень странно объединять две таблицы в столбце с именем «id». По соглашению, столбец «id» представляет нечто уникальное для этой таблицы, поэтому в пользовательской таблице может быть столбец с именем «id», а в таблице учетных записей может быть столбец с именем «user_id».

0 голосов
/ 04 апреля 2020

для вашего SQL, работают следующие тальбы

  • 2Variations => строки: A
  • Вариация_type_link => строки: B
  • Вариация_hashtag_link => строки: C
  • docs_inventory => строки: D
  • документы => строки: E

, поэтому, если ваш исходный запрос будет выполняться, рабочие строки для объединения и где будет A B C D E после A B C D E, будет сгруппирована работа.

улучшение SQL скорости бега. Вы должны уменьшить количество операций и установить индексный ключ.

не волнуйтесь, мы можем улучшить время выполнения:)

# 1 сначала, вы должны проверить, что следующее поле устанавливается индексированием

  • 2Variations => идентификатор, идентификатор продукта
  • Вариация_типа_ссылки => идентификатор, удалено
  • Вариация_hashtag_link => идентификатор, удалено
  • docs_inventory => product_id, doc_id, удален, склад
  • docs => id

# 2 избегать использования между операциями di.warehouse между 1 и 2 : это неправильно для быстрой скорости (склад> = 1 И склад <= 2): хорошо для быстрой скорости </p>

# 3 попробуйте уменьшить количество операций объединения с помощью вспомогательного выбора , если вы показываете мой окончательный запрос, вы можете иметь смысл

Я уверен, что следующий запрос будет работать очень быстро:)

SELECT dtbl.type, dtbl.hashtag, dtbl.warehouse, sum(dtbl.qty)as qty, sum(dtbl.price) as price, sum(dtbl.sold_price) as sold_price, sum(dtbl.cogs) as cogs, avg(dtbl.price) as ave_price, avg(dtbl.sold_price) as ave_sold_price, 
    YEAR(docs.created_on) as year, MONTH(docs.created_on) as month FROM
(
    SELECT btbl.*, di.* FROM
    (
        SELECT atbl.product_id, atbl.type, hashtag.variation_hashtag as hashtag FROM
        (
            SELECT v.id, v.product_id, type.product_type as type FROM
                2Variations as v
            LEFT JOIN
            (
                SELECT id, product_type FROM variations_type_link
                WHERE deleted = 0
            ) as type
            ON v.id = type.id
        ) as atbl
        LEFT JOIN
        (
            SELECT id, variation_hashtag FROM variations_hashtag_link
            WHERE deleted = 0 OR deleted IS NULL {$query_where}
        ) as hashtag
        ON atbl.id = hashtag.id
    ) as btbl
    LEFT JOIN
    (
        SELECT ctbl.*, YEAR(docs.created_on) as year, MONTH(docs.created_on) as month FROM
        (
            SELECT product_id, qty, warehouse, price, sold_price, cogs, price, sold_price FROM docs_inventory
            WHERE deleted = 0 AND ( warehouse >= 1 AND warehouse <= 2 )
        ) as ctbl
        LEFT JOIN
            docs
        ON ctbl.doc_id = docs.id
    ) as di
    ON btbl.product_id = di.product_id
) as dtbl
GROUP BY YEAR(dtbl.created_on), MONTH(dtbl.created_on), {$groups}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...