简体   繁体   English

在where子句和order by子句之间的MySQL索引

[英]MySQL index in between where clause and order by clause

My table structure is something like below: 我的表结构如下所示:

CREATE TABLE test (
    id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,

    field_1 VARCHAR(60) NOT NULL,
    field_2 INT(10) UNSIGNED NULL,
    field_3 INT(10) UNSIGNED NULL,
    field_4 INT(10) UNSIGNED NULL,
    field_5 CHAR(2) NULL,
    field_6 INT(10) UNSIGNED NOT NULL,

    rank TINYINT(2) NOT NULL DEFAULT '0',   
    status TINYINT(3) NOT NULL DEFAULT '0',

    PRIMARY KEY (id),
    INDEX (status)

) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE = MyISAM;

On above table the fields rank and status will have integer value between 0-9 and 0-4 respectively. 在上表中, rankstatus字段的整数值分别为0-9和0-4。

Currently the table is filled with around 950K data and I am trying to optimize my queries as much as possible. 目前,该表中充满了大约950K数据,我正在尝试尽可能优化我的查询。

Basically I need to select fields with some where clause with a descending order on field rank . 基本上,我需要选择带有where子句的字段,其中where子句的字段rank为降序。

For example, below are few sql queries: 例如,以下是一些sql查询:

SELECT field_1, field_2, field_3 FROM test WHERE field_1 = 'data1' && status IN ('0', '1', '2') ORDER BY rank DESC LIMIT 0, 20;
SELECT field_1, field_2, field_3 FROM test WHERE field_2 = '5' && status IN ('1', '2') ORDER BY rank DESC LIMIT 0, 20;
SELECT field_1, field_2, field_3 FROM test WHERE field_5 = 'US' && status IN ('0', '2') ORDER BY rank DESC LIMIT 0, 20;

On above query ORDER BY rank DESC is very important. 在上面的查询中, ORDER BY rank DESC非常重要。 So I am quite confuse whether I should add index on single column or multi-column. 所以我很困惑我应该在单列还是多列上添加索引。

Could anyone suggest me the best solution. 谁能建议我最好的解决方案。

Your key problem is that over 950k rows your status column has up to 4 distinct values. 您的关键问题是,超过950k的行中, status列最多包含4个不同的值。 On a BTREE index, this will be a real pain to process. 在BTREE指数上,这将是一个真正的难题。

Some more effective indexes to use for the 3 queries mentioned are probably the following 下面提到的用于3个查询的一些更有效的索引可能是:

INDEX forQuery1 ( field_1 , status , rank ) USING BTREE,
INDEX forQuery2 ( field_2 , status , rank ) USING BTREE,
INDEX forQuery3 ( field_5 , status , rank ) USING BTREE,

You'll find that the second query especially should benefit however you're still going to have the issue where the variance of the data is very low for the size of dataset and most likely MySQL will fall back to a table scan though your EXPLAIN will probably show the LIMIT to lessen the effect of that. 您会发现第二个查询特别有用,但是您仍然会遇到这样的问题,即数据集的大小的数据差异非常小,尽管您的EXPLAIN会可能会显示LIMIT来减轻这种影响。 The indexes mentioned should be suitable for determining which rows to return though. 提到的索引应该适合于确定要返回哪些行。

For further information on how MySQL uses indexes take a look through 13.1.13. 有关MySQL如何使用索引的更多信息,请浏览13.1.13。 CREATE INDEX Syntax in particular the section on B-Tree Index Characteristics and the following extracts CREATE INDEX语法 ,尤其是有关B树索引特征的部分以及以下摘录

If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to find rows. 如果表具有多列索引,则优化器可以使用索引的任何最左前缀来查找行。 For example, if you have a three-column index on (col1, col2, col3), you have indexed search capabilities on (col1), (col1, col2), and (col1, col2, col3). 例如,如果在(col1,col2,col3)上有一个三列索引,则在(col1),(col1,col2)和(col1,col2,col3)上都有索引搜索功能。

MySQL cannot use an index if the columns do not form a leftmost prefix of the index. 如果列不构成索引的最左前缀,则MySQL无法使用索引。 Suppose that you have the SELECT statements shown here: 假设您在这里显示了SELECT语句:

and

Sometimes MySQL does not use an index, even if one is available. 有时,即使索引可用,MySQL也不使用索引。 One circumstance under which this occurs is when the optimizer estimates that using the index would require MySQL to access a very large percentage of the rows in the table. 发生这种情况的一种情况是,优化器估计使用索引将需要MySQL访问表中很大比例的行。 (In this case, a table scan is likely to be much faster because it requires fewer seeks.) However, if such a query uses LIMIT to retrieve only some of the rows, MySQL uses an index anyway, because it can much more quickly find the few rows to return in the result. (在这种情况下,表扫描可能会更快,因为它需要更少的查找。)但是,如果这样的查询使用LIMIT只检索某些行,则MySQL仍然使用索引,因为它可以更快地找到返回结果的几行。

As an additional note, you don't need to quote numeric data types and so field_2 = 5 && status IN ( 1 , 2 ) is valid (and in fact I have had some strange issue in the past due to quoting integer datatypes instead of specifying them as numerics) 另外需要注意的是,您不需要引用数字数据类型,因此field_2 = 5 && status IN ( 1 , 2 )是有效的(实际上,由于引用整数数据类型而不是引用数据,我过去曾遇到过一些奇怪的问题将其指定为数字)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM