![](/img/trans.png)
[英]MySQL join performance with order by for large tables. Missing index?
[英]MySQL optimized performance for two large tables with same index
我有兩張表,其中包含大量數據(主表約 180 萬,輔助表約 120 萬),如下所示:
訂閱者表(id,名稱,email,國家,account_status,...)subscriber_payment_table(id,subscriber_id,payment_type,payment_credential)
我的最終目標是有一個表,包含所有用戶及其支付表(如果不存在,則為 null),直到昨天,並且 account_status = 1(活動)
大多數訂閱者都有相應的訂閱者付款,因此使用 INNER JOIN 不是一個可行的選擇,並且使用 LEFT JOIN 讓我最終得到 SQL 在經過大量處理工作后 2 小時后我的查詢超時。
SELECT
`subscribers`.`id` AS `id`,
`subscribers`.`email` AS `email`,
`subscribers`.`name` AS `name`,
`subscribers`.`geoloc_country` AS `country`,
`subscribers_payment`.`payment_type` AS `paymentType`,
`subscribers_payment`.`payment_credential` AS `paymentCredential`
`subscribers`.`create_datetime` AS `createdAt`
FROM
`subscribers`
LEFT JOIN
`subscribers_payment` ON (`subscribers_payment`.`subscriberId` = `subscribers`.`id`)
WHERE
`subscribers`.`account_status` = 1
AND DATE_FORMAT(CAST(`subscribers`.`create_datetime` AS DATE), '%Y-%m-%d') < curdate())
如前所述,此查詢花費了太多時間,最終超時且無法正常工作。 我還考慮在“所有訂閱者”和“付費訂閱者”之間建立一個 UNION。
(
SELECT
`subscribers`.`id` AS `id`,
`subscribers`.`email` AS `email`,
`subscribers`.`name` AS `name`,
`subscribers`.`geoloc_country` AS `country`,
null AS `paymentType`,
null AS `paymentCredential`
`subscribers`.`create_datetime` AS `createdAt`
FROM
`subscribers`
WHERE
`subscribers`.`account_status` = 1
AND DATE_FORMAT(CAST(`subscribers`.`create_datetime` AS DATE), '%Y-%m-%d') < curdate()))
UNION
(
SELECT
`subscribers`.`id` AS `id`,
`subscribers`.`email` AS `email`,
`subscribers`.`name` AS `name`,
`subscribers`.`geoloc_country` AS `country`,
`subscribers_payment`.`payment_type` AS `paymentType`,
`subscribers_payment`.`payment_credential` AS `paymentCredential`
`subscribers`.`create_datetime` AS `createdAt`
FROM
`subscribers`
INNERJOIN
`subscribers_payment` ON (`subscribers_payment`.`subscriberId` = `subscribers`.`id`)
WHERE
`subscribers`.`account_status` = 1
AND DATE_FORMAT(CAST(`subscribers`.`create_datetime` AS DATE), '%Y-%m-%d') < curdate()))
當前實現的問題是我得到了重復的查詢(我正在使用 UNION 但它沒有將我的結果組合在一起並刪除非不同的值,這是因為我在paymentType
和paymentCredential
列中有不同的值)
這個查詢運行大約 2 分鍾,所以這對我來說更可行。 我只需要消除重復記錄.. 除非這里有更明智的選擇
免責聲明:我們使用的是 MyISAM 表,因此使用外鍵來加速查詢是不行的。
對於此查詢:
SELECT . . .
FROM subscribers s LEFT JOIN
subscribers_payment sp
ON sp.subscriberId = s.id
WHERE s.account_status = 1 AND
s.create_datetime < curdate();
然后,您需要一個關於subscribers(account_status, create_datetime, id)
和subscribers_payment(subscriberId)
的索引。
我猜測subscriber_payment
上的索引丟失了,這解釋了性能問題。
筆記:
datetime
時間轉換為字符串。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.