简体   繁体   English

如何避免对多可搜索列查询进行全表扫描?

[英]How to avoid full table scan for mutliple searcheable columns query?

I have a following tableA: 我有一个下表:

id | col1 | col2 | col3 | ... | col66
-------------------------------------
999|  1   |  0   |  0   | ... |  1

All the columns colX are searcheable and there are 66 of them which means that creating efficient index is not possible (at least I think so). colX的所有列都是可搜索的,其中有66列,这意味着不可能创建有效的索引(至少我认为是这样)。

The queries may look like that: 查询可能看起来像这样:

SELECT id FROM tableA WHERE col21=1 AND col31=1 AND col64=1

As you can see I only need to retrieve rows with certain columns being set to '1'. 如您所见,我只需要检索某些列设置为“ 1”的行。 The set of columns may vary. 列的集合可能会有所不同。 Do you know any way of doing it without full table scan that is time-consuming? 您是否知道没有耗时的全表扫描的任何方式? I think I have already tried everything but with no luck :-( Thanks! 我想我已经尝试了一切,但没有运气:-(谢谢!

In order for query like this: 为了这样的查询:

SELECT id FROM tableA WHERE col21=1 AND col31=1 AND col64=1

to work fast, you must have created compound index which includes all fields mentioned: (col21, col31, col64) . 为了快速工作,您必须创建包含上述所有字段的复合索引: (col21, col31, col64) I guess you cannot predict list of needed fields upfront, so it probably would not work for you - unless you are willing to create huge number of indexes. 我猜您无法预先预测所需字段的列表,因此它可能对您不起作用-除非您愿意创建大量索引。

Better alternative is to normalize your table - create slave table which will store one attribute in a separate row. 更好的选择是规范化表-创建从表,该表将在一个单独的行中存储一个属性。 This will make indexing much easier, and also makes it possible to keep arbitrary number of attributes. 这将使索引编制变得容易得多,并且还可以保留任意数量的属性。

UPDATE : One more possibility is to replace your 0/1 columns with bitmaps . 更新一种可能性是用位图替换0/1列。 If today you have one 32-bit primary key and 66 tiny int columns, row width is 4+66=70 bytes. 如果今天您有一个32位主键和66个int小列,则行宽为4 + 66 = 70字节。 If you use BIT data type (you will need 2 bit columns, becase max BIT size in MySQL is 64 bits), row width becomes 4+(66/8)=13 bytes, or almost 5 times less than before. 如果使用BIT数据类型(您将需要2位列,假设MySQL中的最大BIT大小为64位),则行宽变为4+(66/8)= 13字节,几乎是以前的5倍。 If today your full scan time is 0.4 seconds, with this packing it would be 0.08 seconds, which might become acceptable for you. 如果今天您的完整扫描时间为0.4秒,使用此包装,它将为0.08秒,您可能会接受。

You can change the structure of your table with something like: 您可以使用以下方式更改表的结构:

id   type  value
999  col1  1
999  col2  0
---

And you can add a artificial PK if you think you need it also the key thing here is to have a composite index on type and value : INDEX (type,value) this way your queries will use this index and the search will be faster. 而且,如果您认为需要它,可以添加一个人工PK,这里的关键是要在类型和值上有一个复合索引: INDEX (type,value)这样您的查询将使用该索引,并且搜索会更快。

Your query will be transformed in : 您的查询将转换为:

SELECT 
    id 
FROM 
    tableA 
WHERE 
    type IN ('col21','col31','col64')
    AND value = 1

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

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