Mysql

簡單的索引選擇查詢需要 350 秒 (?!) 即使過濾 100.00“使用索引條件”

  • January 27, 2019

我的日誌顯示,此處解釋的查詢花費了352.19 秒contact_id(對於和不同的其他類似查詢,時間相似execute_at)。

EXPLAIN SELECT 
   *
FROM
   `automations`
WHERE
   (`contact_id` = 22638
       AND `job_class_name` = 'App\Jobs\MyJob'
       AND `execute_at` = '2018-12-15 16:43:00')
       AND `automations`.`deleted_at` IS NULL
LIMIT 1

解釋的結果:

| id | select_type | table       | partitions | type | possible_keys                  | key                            | key_len | ref                     | rows | filtered | Extra                 |
|----|-------------|-------------|------------|------|--------------------------------|--------------------------------|---------|-------------------------|------|----------|-----------------------|
| 1  | SIMPLE      | automations | NULL       | ref  | cId_job_executeAt_delAt_unique | cId_job_executeAt_delAt_unique | 780     | const,const,const,const | 1    | 100.00   | Using index condition |

我在優化 MySql 方面缺乏經驗,但我的猜測是 Explain 看起來很棒,對吧?

為什麼這樣的查詢需要 350 多秒?如何診斷和修復?

PS這與我經常看到 的E_WARNING: Error while sending STMT_PREPARE packet. PID=* 錯誤有關。

CREATE TABLE `automations` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `contact_id` int(10) unsigned NOT NULL,
 `job_class_name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
 `execute_at` datetime NOT NULL,
 `created_at` timestamp NULL DEFAULT NULL,
 `updated_at` timestamp NULL DEFAULT NULL,
 `deleted_at` timestamp NULL DEFAULT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `cId_job_executeAt_delAt_unique` (`contact_id`,`job_class_name`,`execute_at`,`deleted_at`),
 CONSTRAINT `automations_contact_id_foreign` FOREIGN KEY (`contact_id`) REFERENCES `contacts` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1519 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

我認為需要 352 秒的查詢實際上只用了 0.352 秒!🤦‍♂️

https://laravel.io/forum/03-04-2014-what-time-format-does-dbgetquerylog-return向我展示了 Laravel 將DB::getQueryLog()“時間”顯示為毫秒(微秒乘以 1000),而不是秒。

多麼令人尷尬的錯誤(糟糕的假設)。所以我需要編輯我的 500 分賞金問題:https ://stackoverflow.com/questions/53469793/e-warning-error-while-sending-stmt-prepare-packet-pid/54374937?noredirect=1#comment95579631_53469793

查詢的最佳索引將是具有 4 列的複合索引,順序不限:

INDEX(contact_id, job_class_name, execute_at, deleted_at)

而且,根據您選擇的順序,您可以擺脫現有的 KEY 之一。

注意反斜杠。 'App\Jobs\MyJob' 被視為App[LF]obs[CR]yJobAppJobsMyJob

352秒實在是太不合理了。也許其他事情正在發生,並阻止對行和/或表的訪問?(352s 是假的。)

“使用索引條件”與“使用索引”不同。後者表示一個“覆蓋索引”,對於這個查詢和表來說是不實用的。

引用自:https://dba.stackexchange.com/questions/225068