簡體   English   中英

MySQL“ NOT IN”查詢優化

[英]MySQL “NOT IN” Query Optimization

優化MySQL查詢不是我的專長,因此我想知道是否有人可以幫助我在此處制定最佳查詢(和索引)。

作為背景,我試圖在具有特定位置條件(日期范圍,而不是特定產品等,如您在下面的查詢中看到)的交易表中查找不同的訪客ID。 交易和訪問者之間存在一對多的關系,因此單個訪問者可以進行很多交易。

對結果的另一個要求是,如果在結果中找到了visitor_id, 則它必須是整個表中visitor_id的第一個實例(按date_time) 換句話說,visitor_id僅應存在於主查詢中設置的日期范圍內,並且不應該事先存在。

到目前為止,這是我整理的內容。 它使用NOT IN和一個子查詢,但這似乎並不理想,因為該查詢需要2-3秒的時間,因為該表具有超過50萬條記錄。 我嘗試了一些索引變體,但似乎沒有任何效果。

這是查詢。

SELECT DISTINCT visitor_id, date_time
FROM pt_transactions
WHERE visitor_id NOT IN (SELECT visitor_id FROM pt_transactions WHERE date_time <     '$this->_date_time_start')
AND campaign_id = $this->_campaign_id
AND a_aid = '$a_aid'
AND date_time >= '$this->_date_time_start'
AND date_time <= '$this->_date_time_end'                      
AND product_id != 65

這是完整的表結構。

CREATE TABLE IF NOT EXISTS `pt_transactions` (
  `id` int(32) NOT NULL AUTO_INCREMENT,
  `type` varchar(2) NOT NULL COMMENT 'New Lead (NL), Raw Optin (RO), Base Sale (BS), Upsell Sale (US), Recurring Sale (RS), Base Refund (BR), Upsell Refund (UR), Recurring Refund (RR), Unknown Refund (XR),  or Chargeback (C)',
  `date_time` datetime NOT NULL,
  `amount` varchar(255) NOT NULL,
  `a_aid` varchar(255) NOT NULL,
  `subid1` varchar(255) NOT NULL,
  `subid2` varchar(255) NOT NULL,
  `subid3` varchar(255) NOT NULL,
  `product_id` int(16) NOT NULL,
  `visitor_id` int(32) NOT NULL,
  `campaign_id` int(16) NOT NULL,
  `last_click_id` int(16) NOT NULL,
  `trackback_type` varchar(255) NOT NULL COMMENT 'Shows if the transaction is tracked back to the original visitor via cookie or via IP.  Usually only applies to sales via pixel.',
  `original_transaction_id` int(32) NOT NULL COMMENT 'Reference to original transaction id, in this table, if type is RS, R, or C',
  `recurring_transaction_id` varchar(32) NOT NULL COMMENT 'Reference to existing RecurringTransaction if type is RS',
  PRIMARY KEY (`id`),
  KEY `visitor_id` (`visitor_id`),
  KEY `campaign_id` (`visitor_id`,`campaign_id`,`amount`,`product_id`),
  KEY `transaction_retrieval_group` (`campaign_id`,`date_time`,`a_aid`),
  KEY `type` (`type`),
  KEY `date_time` (`date_time`),
  KEY `original_source` (`campaign_id`,`a_aid`,`date_time`,`product_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=574636 

從您的查詢中我可以理解的是...他們不需要寫NOT IN語句...

因為,您已經在檢查

date_time >= '$this->_date_time_start'

因此,無需在NOT IN語句中檢查date_time < '$this->_date_time_start'

只有下面的應該可以正常工作:)

SELECT DISTINCT visitor_id, date_time
FROM pt_transactions
WHERE 
AND campaign_id = $this->_campaign_id
AND a_aid = '$a_aid'
AND date_time >= '$this->_date_time_start'
AND date_time <= '$this->_date_time_end'                      
AND product_id != 65

您可以嘗試NOT EXISTS

SELECT DISTINCT visitor_id, date_time
  FROM pt_transactions t
 WHERE campaign_id = $this->_campaign_id
   AND a_aid = '$a_aid'
   AND date_time >= '$this->_date_time_start'
   AND date_time <= '$this->_date_time_end'                      
   AND product_id != 65
   AND NOT EXISTS 
(
  SELECT * 
    FROM pt_transactions 
   WHERE visitor_id = t.visitor_id
     AND date_time < '$this->_date_time_start'
)

執行EXPLAIN <query>並查看如何使用索引。 如果您願意,可以以文本形式發布問題中的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM