Mysql

為什麼索引沒有加速多連接查詢

  • September 22, 2016

好的,所以我有 3 個表:聯繫人、便箋和 lastContact。

問題是: 1) 每當我想將聯繫人雙重連接到其他 2 個表時,查詢會在 15-60 分鐘內爆炸。2)為什麼使用目前索引只是主表中的主鍵計數到其他 2 個表需要這麼多時間?

它們都有一個共同的鍵,除了音符之外是獨一無二的。

(結構簡化刪除所有不必要的列)

   CREATE TABLE `contacts` (
   `contactID` int(10) unsigned NOT NULL AUTO_INCREMENT,
   `firstName` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
   `lastName` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
   `phone` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL,
   `mobilePhone` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL,
   `altPhone` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL,
   `street` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
   `city` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL,
   `state` varchar(3) COLLATE utf8_unicode_ci DEFAULT NULL,
   `postalCode` varchar(12) COLLATE utf8_unicode_ci DEFAULT NULL,
   `email` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
   `source` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
   `owner` varchar(64) unsigned DEFAULT NULL,
   PRIMARY KEY (`contactID`),
   KEY `phone` (`phone`),
   KEY `phones` (`phone`,`mobilePhone`,`altPhone`),
   KEY `owner` (`owner`),
   KEY `source` (`contactID`,`source`,`owner`)
   ) ENGINE=InnoDB AUTO_INCREMENT=119138 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

   CREATE TABLE `contacts_notes` (
   `noteID` int(10) unsigned NOT NULL AUTO_INCREMENT,
   `contactID` int(10) unsigned DEFAULT NULL,
   `notes` text,
   `dateline` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
   PRIMARY KEY (`noteID`),
   KEY `contactID` (`contactID`)
   ) ENGINE=Aria AUTO_INCREMENT=1486 DEFAULT CHARSET=utf8 PAGE_CHECKSUM=1;

   CREATE TABLE `lastContacts` (
   `contactID` varchar(32) COLLATE utf8_unicode_ci NOT NULL,
   `ultimo` datetime DEFAULT NULL,
   `callID` int(10) unsigned DEFAULT NULL,
   `userName` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL,
   `lastContact` datetime DEFAULT NULL,
   `callCount` tinyint(3) unsigned DEFAULT NULL,
   PRIMARY KEY (`contactID`),
   KEY `callid` (`callID`),
   KEY `ultimo` (`ultimo`),
   KEY `username` (`userName`)
   ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

在contacts 和lastContacts 中有~50k 記錄,contact_notes 有~1k。

查詢是:

SELECT COUNT(*) total FROM (
   SELECT l.contactID FROM contacts l
   LEFT JOIN lastContacts lc ON l.contactID = lc.contactID
   WHERE lc.contactID IS NULL 
) x 
LEFT JOIN contacts_notes ln ON x.contactID = ln.contactID
WHERE  ln.contactID IS NULL

@Jehad Keraki 提供了答案。表lastContacts的主鍵列ContactID被定義為字元串,而其他每個表中的同一列是整數。在該列上連接表會導致隱式轉換並導致性能不佳。

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