Индексация с использованием функции to_char (timestamp, 'YYYY-MM-DD'))

В моем SQL-предложении where есть следующее. Это работает с базой данных Oracle. Поле timestamp определяется в базе данных как поле timestimp. мой выборочный запрос:

create index ind_timestamp on sms_in(to_char(timestamp,'YYYY-MM-DD'));

select * from sms_in where to_char(timestamp,'YYYY-MM-DD')in '2018-08-01';

но когда я пытаюсь выполнить запрос, доступ к базе данных заполнен. Это означает, что индексация не работает.

Хотите знать, почему в запросе есть предложение IN, а не =?

Andrew 07.08.2018 14:30

Как изменится план, если вы поменяете in на =? Кроме того, сколько строк в вашей таблице, и сколько из этих строк имеют TO_CHAR(TIMESTAMP, 'YYYY-MM-DD') , равный 2018-08-01? Кроме того, когда вы в последний раз собирали статистику по этой таблице? Используйте SELECT LAST_ANALYZED FROM USER_TABLES WHERE TABLE_NAME = 'SMS_IN', чтобы узнать.

Bob Jarvis - Reinstate Monica 07.08.2018 14:30

Кроме того, лучше запустить dbms_stats.gather_table_stats () для таблицы sms_in, чтобы обновить вычисления оптимизатора.

Dmitriy Yankin 07.08.2018 14:32

почему вы используете индекс на основе функций, добавьте индекс в столбец временной метки и преобразуйте свою строку в метку времени в предложении where

hotfix 07.08.2018 14:32

Результат запроса правильный, проблема в индексе, он не работает.

Dach Ch 07.08.2018 14:36

также я использую индексацию, потому что таблица содержит более 100К записей. При извлечении записей загрузка процессора достигает 100%.

Dach Ch 07.08.2018 14:37

я не говорю, что вам не следует использовать индекс. вы должны использовать обычный индекс для столбца, а не индекс на основе функции

hotfix 07.08.2018 14:39

@hotfix - этот механизм не будет работать без дополнительных усилий с запросом, to_char обрезает метку времени, удаляя элемент времени. Если он преобразует дату в метку времени, по умолчанию это будет полночь и не будет совпадать без дополнительной логики / усилий (это предполагает, что его метки времени не установлены как чистые даты)

Andrew 07.08.2018 14:40

@Andrew, он мог бы использовать between 00:00:00 and 23:59:59, и он должен использовать индекс

hotfix 07.08.2018 14:44

@ Андрей, верно, я использую метку времени в другом формате.

Dach Ch 07.08.2018 14:49

@hotfix - согласен, это дополнительная работа с запросами, которую, как мне кажется, нужно прояснить, если вы напишете свой комментарий в ответе.

Andrew 07.08.2018 14:50

@hotfix этот механизм не работает.

Dach Ch 07.08.2018 14:50

Сколько разных дат в таблице? (select count(distinct trunc(timestamp)) from sms_in) СУБД будет использовать индекс только тогда, когда ожидает, что только небольшая часть таблицы будет соответствовать критериям. А предложение IN значительно снижает вероятность использования индекса. Это не проблема; полное сканирование таблицы, даже для миллионов строк, по-прежнему может быть быстрее, чем доступ к индексу. И это 100% использование ЦП само по себе тоже неплохо.

Thorsten Kettner 07.08.2018 14:50

@ThorstenKettner в таблице 215 разных дат.

Dach Ch 07.08.2018 14:55

@DachCh, я не вижу причины, почему? ты должен сказать мне, почему это не работает.

hotfix 07.08.2018 14:59

@hotfix доступ к таблице заполнен, он стоит 4014, как будто я не использую индекс.

Dach Ch 07.08.2018 15:08

@DachCh добавить свой план выполнения

hotfix 07.08.2018 15:10

Лучше бы создать индекс по TRUNC(timestamp)

Wernfried Domscheit 07.08.2018 15:14
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
18
1 689
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы всегда ищете данные за определенный день, то я предлагаю следующее.

вы добавляете обычный индекс в столбец timestamp

create index ind_timestamp on sms_in(timestamp);

ваш выбор может выглядеть как

select * 
  from sms_in 
 where timestamp between to_date('2018-08-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') 
                     and to_date('2018-08-01 23:59:59','YYYY-MM-DD HH24:MI:SS');

или ты можешь сделать это как

select * 
  from sms_in 
 where timestamp >= to_date('2018-08-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
  and timestamp  <= to_date('2018-08-01 23:59:59','YYYY-MM-DD HH24:MI:SS');

Обновлено:

Этот ответ в основном правильный, но логика должна быть такой:

select * 
 from sms_in 
 where timestamp >= date '2018-08-01' and
       timestamp < date '2018-08-02 ;

Это не приведет к получению каких-либо временных меток между 23:59:59.999000001 и 23:59:59.999999999, вам лучше использовать `WHERE timestamp> = TIMESTAMP '2018-01-01 00:00:00' И временную метку <TIMESTAMP '2018-01-02 00:00:00'.

MT0 07.08.2018 14:57

вы правы, но сначала мы должны узнать, как выглядят данные в его таблице. может он просто спасет FF3

hotfix 07.08.2018 15:01

Тип столбца метки времени - дата, он выглядит как «ГГГГ-ММ-ДД». Но я использую другой запрос, где мне нужны только «ГГГГ-ММ», «ГГГГ» или «ММ» и т. д. Это зависит от того, что я получаю.

Dach Ch 07.08.2018 15:03

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

hotfix 07.08.2018 15:08

Это правильный ответ, но я не знаю, как получить его на следующий день («2018-08-02»).

Dach Ch 07.08.2018 15:30
date '2018-08-01' +1
hotfix 07.08.2018 15:32

Другие вопросы по теме