使用索引提高查询性能

Sco*_*ott 5 mysql index

我希望为数据库创建索引以实现更好的性能。我正在使用这个查询:

SELECT DISTINCT t1.* FROM current_order
AS t1 LEFT JOIN
receipt AS t2 USING (paper_id,subscriber_id)
WHERE t2.id NOT IN (SELECT id
FROM receipt WHERE paid_till_date > Now())
UNION
SELECT current_order.* FROM receipt RIGHT JOIN
current_order USING (paper_id, subscriber_id)
Where receipt.id IS NULL ORDER BY
subscriber_id, paper_id
Run Code Online (Sandbox Code Playgroud)

表是:

 PAPER
    id
    name

 SUBSCRIBER
    id
    name
    address
    suburb
    state
    postcode
    round_id

 CURRENT ORDER
    paper_id
    subscriber_id

 ROUND
    id
    name
    paperboy

 RECEIPT
    id
    receipt_date
    paid_till_date
    paper_id
    subscriber_id
Run Code Online (Sandbox Code Playgroud)

我知道主键已经被索引,我应该使用一个索引,其中 WHERE 子句和 ORDER BY 子句经常使用。所以我假设订阅者名称将是一个很好的索引?还有收货日期?

任何提示表示赞赏

mir*_*173 2

原始查询

SELECT DISTINCT t1.* 
  FROM current_order AS t1 
    LEFT JOIN receipt AS t2 USING (paper_id,subscriber_id)
  WHERE t2.id NOT IN (
    SELECT id
      FROM receipt 
      WHERE paid_till_date > Now()
    )
UNION
  SELECT current_order.* 
    FROM receipt 
      RIGHT JOIN current_order USING (paper_id, subscriber_id)
    WHERE receipt.id IS NULL 
    ORDER BY subscriber_id, paper_id
Run Code Online (Sandbox Code Playgroud)

比必要的更复杂。

基表是

CURRENT ORDER
  paper_id
  subscriber_id 
Run Code Online (Sandbox Code Playgroud)

RECEIPT
  id
  receipt_date
  paid_till_date
  paper_id
  subscriber_id 
Run Code Online (Sandbox Code Playgroud)

OP 指出这receipt.id是主键,我认为这(paper_id,subscriber_id)是主键current order

两个查询

SELECT t1.* 
  FROM current_order AS t1 
    LEFT JOIN receipt AS t2 USING (paper_id,subscriber_id)
  WHERE t2.id NOT IN (
    SELECT id
      FROM receipt 
      WHERE paid_till_date > Now()
    )
Run Code Online (Sandbox Code Playgroud)

SELECT t1.* 
  FROM current_order AS t1 
    LEFT JOIN receipt AS t2 USING (paper_id,subscriber_id)
  WHERE paid_till_date <= Now()
    or paid_till_date  is NULL
Run Code Online (Sandbox Code Playgroud)

是等价的:两个查询的结果集恰好包含以下元组:

all tuples from current_order where there is a RECEIPT with the same (paper_id,subscriber_id) and paid_till_date <= Now()
all tuples from current_order where there is a RECEIPT with the same (paper_id,subscriber_id) and paid_till_date is NULL
all tuples from current_order where there is no RECEIPT with the same (paper_id,subscriber_id) (and therefore paid_till_date  is NULL)
Run Code Online (Sandbox Code Playgroud)

因此,查询是等效的。如果将 DISTINCT 添加到 select 子句,它们也是等效的。

查询的结果集

  SELECT current_order.* 
    FROM receipt 
      RIGHT JOIN current_order USING (paper_id, subscriber_id)
    WHERE receipt.id IS NULL 
    ORDER BY subscriber_id, paper_id
Run Code Online (Sandbox Code Playgroud)

包含以下元组

all tuples from current_order where there is no RECEIPT with the same (paper_id,subscriber_id) (and therefore receipt.id is NULL)
Run Code Online (Sandbox Code Playgroud)

所以原来的查询可以改为更简单的查询

SELECT DISTINCT t1.* 
  FROM current_order AS t1 
    LEFT JOIN receipt AS t2 USING (paper_id,subscriber_id)
  WHERE paid_till_date <= Now()
    or paid_till_date  is NULL
Run Code Online (Sandbox Code Playgroud)

也许 (paper_id,subscriber_id,paid_till_date) 上的索引会很有用。该查询仅使用索引中找到的列(不再使用receipt.id)。“当前订单”的 (paper_id,subscriber_id) 上的索引已存在,因为这是主键。