加速查询:ORDER BY和LIMIT(索引?)

时间:2013-02-26 03:02:08

标签: mysql performance perl sorting

我试图从基因表中找到最接近的基因,给定位置信息。这是一个例子:

  

SELECT chrom, txStart, txEnd, name2, strand FROM wgEncodeGencodeCompV12 WHERE chrom = 'chr1' AND txStart < 713885 AND strand = '+' ORDER BY txStart DESC LIMIT 1;

我的测试运行速度非常慢,这是有问题的。

以下是带有默认索引(EXPLAIN)的chrom输出:

  

| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  | 1 | SIMPLE | wgEncodeGencodeCompV12 | ref | chrom | chrom | 257 | const | 15843 | Using where; Using filesort |

使用了Filesort并且可能导致所有的迟缓?

我尝试通过索引(chrom, txStart, strand)或仅txStart来加快排序速度,但它只会变慢(?)。我的理由是txStart没有足够的选择性来成为一个好的索引,在这种情况下整个表扫描实际上更快?

以下是带有附加索引的EXPLAIN输出:

  

| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  | 1 | SIMPLE | wgEncodeGencodeCompV12 | range | chrom,closest_gene_lookup | closest_gene_lookup | 261 | NULL | 57 | Using where |

     

| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
  | 1 | SIMPLE | wgEncodeGencodeCompV12 | range | chrom,txStart | txStart | 4 | NULL | 1571 | Using where |

表格结构

  

CREATE TABLE wgEncodeGencodeCompV12 (
smallint(5) unsigned NOT NULL,
名称varchar(255) NOT NULL,
CHROM varchar(255) NOT NULL,
char(1) NOT NULL,
TXSTART int(10) unsigned NOT NULL,
TXEND int(10) unsigned NOT NULL,
cdsStart int(10) unsigned NOT NULL,
cdsEnd int(10) unsigned NOT NULL,
exonCount int(10) unsigned NOT NULL,
exonStarts longblob NOT NULL,
exonEnds longblob NOT NULL,
得分int(11) default NULL,
NAME2 varchar(255) NOT NULL,
cdsStartStat enum('none','unk','incmpl','cmpl') NOT NULL,
cdsEndStat { {1}} exonFrames enum('none','unk','incmpl','cmpl') NOT NULL,
CHROM longblob NOT NULL,
KEY
CHROM (,名称),
KEY
名称( NAME2 ),
KEY
NAME2 {{1 }}

有没有办法让这更有效率?我很感激你的时间!

(更新)解决方案: 结合两位评论者的建议显着改善了运行时间。

2 个答案:

答案 0 :(得分:1)

您想要的索引是:wgEncodeGencodeCompV12(chrom, strand, txstart)

通常,您希望将具有相等性的字段作为索引中的第一列。然后添加一个带有不等式的字段。

答案 1 :(得分:1)

在您的情况下(查询单个表,没有连接,没有复杂的东西),了解每列中值的分布以及了解数据库服务器如何使用索引非常重要。如果某个字段具有相当大范围的不同值,则应使用该字段进行索引。 (例如,strand上的索引只会将整个数据拆分为+-,下游过滤器必须处理+或{{1}的每一行结果集,那是最糟糕的情况)

到目前为止,我们知道-在查询的有趣列中具有最有区别的值分布。

因此,您的查询肯定应该利用该列的索引查询!但是btree索引,而不是哈希索引(运算符txStart<<=等在btree上是快速的,但在哈希值上却没有。)

>上只使用一个(btree)索引再试一次(我知道你已经尝试过了,但请再试一次,避免所有二级索引等。)。

多列索引很好,但是它们的复杂性使它们没有普通单列索引那么快,MySQL优化器在选择最佳索引时相当愚蠢; - )

另一个重要因素可能是动态行大小(因为使用txStart列)。但在这方面我还不了解当前的MySQL状态。

相关问题