2017-02-22 79 views
2

У меня есть большая таблица ir_data (150 ГБ), которая содержит данные для разных дат (column val_date). Мне нужно знать, доступна ли данная дата в ir_data в разных точках моего приложения.Недоумение производительности сканирования индекса. Почему индекс сканирования медленный, хотя набор результатов является небольшим и индексируется

select distinct(val_date) from ir_data 

I следующий эксперимент ir_data содержит 29 различных значений для val_date.


УСТАНОВКА 1

Я ожидал, что индекс по ir_data (val_date, KEY_ID, other_colum), чтобы помочь найти 29 значений быстро. На самом деле это занимает более 5 минут:

запроса 1 из 1, строки следующим образом: 29, истекшее время (секунды) - Итого: 343.96, SQL запрос: 343.958, Чтение результатов: 0,002

Я всегда ожидал, что индекс будет деревом, где узлы хранятся в древовидной структуре, например например

val_date -> key_id -> other_column -> data-nodes 

1.1.2017 -> 0-50  -> A   -> (1.1.2017, 0, Automobile), (1.1.2017, 2, Amsterdam) 
        -> B-E   -> (1.1.2017, 12, Batman) 
     -> 51-100 -> A   -> ... 
         X 
     -> 666-1000 -> A 
        -> B-C 
        -> E 
2.1.2017 -> ... 

Основываясь на этой структуре, получение 29 разных значений val_dates должно быть очень быстрым.

Вопрос: Почему это так долго?

Подпункт: есть ли способ исправить это, не создавая другую таблицу?


НАСТРОЙКИ 2

я создал еще один индекс, который содержит только val_date. Это занимает примерно столько же времени.


Query-план:

The type of query is SELECT. 

2 operator(s) under root 

    |ROOT:EMIT Operator (VA = 2) 
    | 
    | |GROUP SORTED Operator (VA = 1) 
    | |Distinct 
    | | 
    | | |SCAN Operator (VA = 0) 
    | | | FROM TABLE 
    | | | ir_data 
    | | | Index : ir_data_idx1 <-- this is the index containing only val_date. 
    | | | Forward Scan. 
    | | | Positioning at index start. 
    | | | Index contains all needed columns. Base table will not be read. 
    | | | Using I/O Size 16 Kbytes for index leaf pages. 
    | | | With MRU Buffer Replacement Strategy for index leaf pages. 
+1

Каков ваш запрос? –

+0

@ OfirWinegarten Да, я должен был упомянуть об этом. Добавлен. – Beginner

ответ

2

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

Как первый шаг, вы можете попробовать update index statistics по индексу, хотя я действительно не думаю, что это поможет.

Если это одноразовая ручная операция, я думаю, вы останетесь довольны работой 5 минут.

Если это запрос, выполняемый ваше приложение, то у вас есть 2 варианта я могу думать:

  1. Как вы сказали, в этом вопросе - нормализуют таблицу, создав дополнительную таблицу для дат и использование FK.
  2. Создать precomputed result set. Это материализованное представление - результаты хранятся как обычная таблица (в отличие от представления, где хранится только его определение).
    Он автоматически обновит результаты в представлении, и значения будут быстро восстановлены.
    Важно: как индексы, это будет иметь влияние на производительность вставки, обновления ...
    Это может выглядеть следующим образом:

    create precomputed result set prs_ir_data 
    immediate refresh 
    as 
    select distinct val_date 
    from ir_data 
    

Вы можете прочитать here и here о предвычисленными результате set

+0

Спасибо. Вы знаете, какую структуру данных они используют? Мне трудно понять, почему нужно обязательно сканировать весь индекс, чтобы найти атрибут верхнего уровня структуры поиска. – Beginner

+0

Идея внешнего ключа очень хорошая, я об этом не думал. – Beginner

+0

Рад, что я мог помочь. Я не уверен в внутренней структуре индексов sybases, но, безусловно, это что-то вроде b-tree для быстрого поиска и вставки. –

0

A recursive CTE значительно ускоряет этот запрос, то есть очень мало отдельных значений в большой таблице. Проблема в том, что поиск индекса во время поиска отдельных значений в настоящее время не выполняется. Вот link to the approach.