来自连接表性能的ORDER BY列

时间:2018-03-24 16:02:49

标签: mysql mariadb

我该如何改进?它需要大约半秒钟,它只是一个演示查询。 这里的问题是ORDER BY,但我不能没有它。对于something表中缺少的记录,我还需要LEFT JOIN的空行。

SELECT c.name 
FROM customers c 
LEFT JOIN something s USING(customer_id) 
ORDER BY s.test DESC LIMIT 25

数据库架构:

CREATE TABLE customers (
 customer_id int(11) NOT NULL AUTO_INCREMENT,
 name text NOT NULL,
 PRIMARY KEY (customer_id),
 KEY namne (name(999))
) ENGINE=MyISAM AUTO_INCREMENT=100001 DEFAULT CHARSET=latin

CREATE TABLE something (
 id int(11) NOT NULL AUTO_INCREMENT,
 customer_id int(11) NOT NULL,
 text longtext NOT NULL,
 test varchar(5) NOT NULL,
 PRIMARY KEY (id),
 KEY customer_id (customer_id),
 KEY text (text(999)),
 KEY test (test),
 KEY asdasd (customer_id,test)
) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1

说明:

+------+-------------+-------+------+--------------------+--------+---------+--------------------+--------+---------------------------------+
| id   | select_type | table | type | possible_keys      | key    | key_len | ref                | rows   | Extra                           |
+------+-------------+-------+------+--------------------+--------+---------+--------------------+--------+---------------------------------+
|    1 | SIMPLE      | c     | ALL  | NULL               | NULL   | NULL    | NULL               | 100000 | Using temporary; Using filesort |
|    1 | SIMPLE      | s     | ref  | customer_id,asdasd | asdasd | 4       | test.c.customer_id |      2 | Using index                     |
+------+-------------+-------+------+--------------------+--------+---------+--------------------+--------+---------------------------------+

2 个答案:

答案 0 :(得分:0)

LEFT JOIN看起来不像这里。如果用INNER JOIN替换它,引擎将能够使用KEY test (test)作为ORDER BY子句。所以你需要的就是这个:

SELECT c.name 
FROM customers c 
INNER JOIN something s USING(customer_id) 
ORDER BY s.test DESC LIMIT 25

但要获得与LEFT JOIN完全相同的结果,您可以将两个快速查询与UNION ALL结合使用:

(
    SELECT c.name 
    FROM customers c 
    LEFT JOIN something s USING(customer_id) 
    ORDER BY s.test DESC LIMIT 25
) UNION ALL (
    SELECT c.name 
    FROM customers c 
    LEFT JOIN something s USING(customer_id)
    WHERE s.customer_id IS NULL
    LIMIT 25
)
LIMIT 25

答案 1 :(得分:0)

  • 使用InnoDB,而不是MyISAM。
  • VARCHAR(..)而非TEXT中使用一些合理的限制。
  • 如果可能,请删除“前缀索引”。
  • {li> INDEX(a)INDEX(a,b)。时是多余的

更快的速度:

SELECT  name
    FROM  ( 
            (  SELECT  c.name, s.test
                    FROM  customers c
                    JOIN  something s USING(customer_id)
                    ORDER BY  s.test DESC
                    LIMIT  25
            )
        UNION ALL
            (  SELECT  c.name, NULL
                    FROM  customers c
                    LEFT JOIN  something s USING(customer_id)
                    WHERE  s.test IS NULL
                    LIMIT  25
            ) 
        ) AS x
    ORDER BY  test DESC
    LIMIT  25

并且

INDEX(test, customer_id)