2013-06-21 3 views
0

У меня есть следующий TABLEA:Как избежать полного сканирования таблицы для запроса mutliple searchingable columns?

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

Все столбцы colX являются и возможен поиск Есть 66 из них, что означает, что создание эффективного индекса не представляется возможным (по крайней мере я так думаю).

Запросы могут выглядеть так:

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

Как вы можете видеть, что я только нужно извлекать строки с определенным столбцам быть установлен в «1». Набор столбцов может отличаться. Знаете ли вы какой-либо способ сделать это без полного сканирования таблицы, требующего много времени? Я думаю, что я уже попробовал все, но не повезло :-(Спасибо

+0

Действительно ли эти запросы медленны или вы просто не можете согласиться с тем, что mysql использует полное сканирование? – peterm

+0

@peterm Они на самом деле медленные. Я бы не возражал против полного сканирования таблицы, если в таблице было всего 5 строк :-) В моем случае для выполнения запроса, который недопустим, требуется около 0,4 секунды. –

ответ

1

Вы можете изменить структуру вашего стола что-то вроде:

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

И вы можете добавить искусственный PK, если вы считаете, что вы это нужно также ключевая вещь здесь иметь составной индекс по типу и значению:. INDEX (type,value) Таким образом, ваши запросы будут использовать этот индекс и поиск будет быстрее

Ваш запрос будет преобразован в:

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

Это очень расточительное решение. Исходная строка впустую '70' байт. Это будет использовать '(4 + 4 + 1) * 66' =' 594' байт для хранения той же информации или почти в 10 раз больше. – mvp

+0

Я согласен, но тип может быть нормирован на tinyint, который сэкономит место, и ваше решение с растровыми изображениями будет идеальным, если единственные значения для столбцов равны 1 и 0. – Stephan

+0

@Stephan В этом случае (если BIT используется только для одного столбца) MySQL будет выделите для него один байт, который фактически равен TINYINT. –

2

Для того запроса, как это:

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

работать быстро, вы должны создать составной индекс, который включает в себя все поля, указанные: (col21, col31, col64). Я думаю, вы не можете заранее предсказать список необходимых полей, поэтому он, вероятно, не сработает для вас - если вы не хотите создавать огромное количество индексов.

Лучшая альтернатива - нормализовать таблицу - создать рабочую таблицу, которая будет хранить один атрибут в отдельной строке. Это упростит индексирование, а также позволит сохранить произвольное количество атрибутов.

ОБНОВЛЕНИЕ: Еще одна возможность заменить ваши столбцы 0/1 на bitmaps. Если сегодня у вас есть один 32-разрядный первичный ключ и 66 крошечных столбцов int, ширина строки равна 4 + 66 = 70 байт. Если вы используете тип данных BIT (вам понадобятся 2-битные столбцы, размер BIT для максимального размера в MySQL составляет 64 бита), ширина строки становится равной 4+ (66/8) = 13 байт или почти в 5 раз меньше, чем раньше. Если сегодня ваше полное время сканирования составляет 0,4 секунды, с этой упаковкой будет 0,08 секунды, что может стать приемлемым для вас.

+1

+1 для think-alike :) – Stephan

+0

добавлена ​​альтернатива использованию [типа данных BIT] (http://dev.mysql.com/doc/refman/5.5/en/bit-type.html) – mvp

+0

Я рассматривал возможность использования типа BIT, но он имеет один ОЧЕНЬ важный недостаток - трудно найти, то есть col40 = 1 AND col50 = 1. Причина этого в том, что мне нужно игнорировать другие значения столбцов, что означает, что мне нужно использовать побитовое И (&), которое в 2 раза быстрее, чем текущее решение, но все же слишком медленное. –

Смежные вопросы