2010-09-13 2 views
4

Мне интересно, как Google это делает. У меня много медленных запросов, когда речь идет о количестве страниц и общем количестве результатов. Google возвращает значение счета 250 000,00 за долю секунды.SQL-сортировка, пейджинг, фильтрация лучших практик в ASP.NET

Я имею дело с видами сетки. Я создал собственный пейджер для gridview, который требует, чтобы SQL-запрос возвращал количество страниц на основе фильтров, установленных пользователем. Фильтры не менее 5, которые включают ключевое слово, категорию и подкатегорию, фильтр диапазона дат и фильтр сортировки сортировки для сортировки. Запрос содержит около 10 массивных табличных левых объединений.

Этот запрос выполняется каждый раз, когда выполняется поиск, а выполнение запроса выполняется в среднем 30 секунд - будь то подсчет или выбор. Я считаю, что это замедляет работу, это моя строка запросов включительных и эксклюзивных фильтров диапазона дат. Я заменил (< =,> =) на МЕЖДУ И И, но все же я испытываю ту же проблему.

Смотрите запрос здесь: http://friendpaste.com/4G2uZexRfhd3sSVROqjZEc

У меня есть проблемы с параметром долго Диапазон дат.

Проверьте свою таблицу, содержащую даты: http://friendpaste.com/1HrC0L62hFR4DghE6ypIRp

UPDATE [9/17/2010] Я минимизированы мою дату запроса и убрано время. Я попытался уменьшить объединение для моего запроса на подсчет (у меня на самом деле проблема с моим счетчиком фильтров, который занимает много времени, чтобы вернуть результат из 60 тыс. Строк).

 SELECT COUNT(DISTINCT esched.course_id) 
     FROM courses c 
      LEFT JOIN events_schedule esched 
       ON c.course_id = esched.course_id 
      LEFT JOIN course_categories cc 
       ON cc.course_id = c.course_id 
      LEFT JOIN categories cat 
       ON cat.category_id = cc.category_id 
    WHERE  1 = 1 
      AND c.course_type = 1 
      AND active = 1 
      AND c.country_id = 52 
      AND c.course_title LIKE '%cook%' 
      AND cat.main_category_id = 40 
      AND cat.category_id = 360 
AND (

    (2010-09-01' <= esched.date_start OR 2010-09-01' <= esched.date_end) 
    AND 

    ('2010-09-25' >= esched.date_start OR '2010-09-25' >= esched.date_end)  
    ) 

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

Эти статические поля:

AND c.course_type = 1 
AND active = 1 
AND c.country_id = 52 

UPDATE [9/17/2010] Если создать хеш для этих трех полей и сохранить его на одном поле будет делать изменения в скорости?

Это мои динамические поля:

AND c.course_title LIKE '%cook%' 
AND cat.main_category_id = 40 
AND cat.category_id = 360 
// ?DateStart and ?DateEnd 

UPDATE [9/17/2010]. Теперь моя проблема является ведущим% в LIKE запроса

Вывесит обновленный объяснить

+1

Вы применили соответствующие индексы к соответствующим полям поиска? –

+0

Привет, У меня нет доступа к базе данных прямо сейчас. Обновит вас, ребята, завтра. –

+0

«Запрос содержит около 10 массивных табличных левых соединений» - это, безусловно, не помогает;) – eglasius

ответ

3

Поисковые системы, как Google использовать очень сложные закулисный algorythyms в поисках индексов. По сути, они уже определили, какие слова встречаются на каждой странице, а также относительная важность этих слов и относительная важность страниц (по сравнению с другими страницами). Эти индексы очень быстры, потому что они основаны на Побитовое индексирование.

Рассмотрим следующие Google поиск:

custom : 542 million google hits 
pager : 10.8 m 
custom pager 1.26 m 

По сути то, что они сделали, создается запись для слова обычая и в этой записи они разместили 1 для каждой страницы, которая содержит его и 0 для каждого страницы, которая не содержит его. Затем они застегивают его, потому что есть намного больше 0, чем 1 с. Они делают то же самое для пейджера.

Когда приходит поиск custom pager, они разархивируют обе записи, выполняют побитовое И на них, и это приводит к массиву бит, где длина - это общее количество страниц, которые они проиндексировали, и число 1s представляет собой хит рассчитывать на поиск. Позиция каждого бита соответствует определенному результату, который известен заранее, и им нужно только просмотреть подробные сведения о первых 10 для отображения на первой странице.

Это упрощенно, но это общий принцип.

О да, у них также есть огромные банки серверов, выполняющие индексирование и огромные банки серверов, отвечающие запросам на поиск. ОГРОМНЫЕ банки серверов!

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

Теперь, на ваш вопрос: Не могли бы вы вставить пример SQL для нас?

Одна вещь, которую вы могли бы попробовать, это изменить порядок отображения таблиц и объединений в инструкции SQl. Я знаю, что кажется, что это не должно иметь значения, но это, безусловно, может. Если вы ставите наиболее ограничительные объединения ранее в инструкции, то вы вполне можете получить меньше общих объединений, выполненных в базе данных.

Настоящий пример мира. Скажем, вы хотели найти все записи в телефонной книге под именем «Джонсон», номер которой начинался с «7». Один из способов - найти все числа, начинающиеся с 7, а затем присоединиться к ним с цифрами, принадлежащими людям, называемым «Джонсон». На самом деле было бы гораздо быстрее выполнить фильтрацию по-другому, даже если у вас есть индексирование как по именам, так и по номерам. Это связано с тем, что имя «Джонсон» более ограничительное, чем номер 7.

Таким образом, порядок подсчитывается, и программное обеспечение datbase не всегда хорошо определяет заранее, какое соединение необходимо выполнить в первую очередь. Я не уверен в MySQL, так как мой опыт в основном связан с SQL Server, который использует статистику индексов для расчета того, какой заказ выполнять объединения. Эти статистические данные устаревают после нескольких вставок, обновлений и удалений, поэтому их необходимо периодически пересчитывать. Если MySQL имеет что-то подобное, вы можете попробовать это.

ОБНОВЛЕНИЕ Я просмотрел запрос, который вы разместили. Десять левых объединений не являются необычными и должны выполняться нормально, если у вас есть нужные индексы. Твой не сложный запрос.

Что вам нужно сделать, так это разбить этот запрос на его основные принципы. Комментируйте объединения поиска, такие как те, которые указаны в валюте, курсах курса, странах, штатах и ​​городах, а также соответствующие поля в заявлении select. Он все еще работает так же медленно? Возможно нет. Но он, вероятно, еще не идеален.

Итак, прокомментируйте все остальное, пока у вас не будет курсов и группы по курсу id и order by courseid. Затем, экспериментируйте с добавлением в левом соединении, чтобы увидеть, какой из них имеет наибольшее влияние. Затем, сосредоточив внимание на тех, которые оказывают наибольшее влияние на производительность, измените порядок запросов. Это метод проб и ошибок.Было бы намного лучше посмотреть на индексы столбцов, в которые вы входите.

Например, для строки cm.method_id = c.method_id потребуется первичный ключ на курсах_methodologies.method_id и индекс внешнего ключа на курсах.method_id и т. Д. Кроме того, для всех полей в разделах where, group by и order by нужны индексы.

Успехов

UPDATE 2 Вы серьезно должны смотреть на дату фильтрации по этому запросу. Что ты пытаешься сделать?

AND ((('2010-09-01 00:00:00' <= esched.date_start 
      AND esched.date_start <= '2010-09-25 00:00:00') 
     OR ('2010-09-01 00:00:00' <= esched.date_end 
      AND esched.date_end <= '2010-09-25 00:00:00')) 
     OR ((esched.date_start <= '2010-09-01 00:00:00' 
      AND '2010-09-01 00:00:00' <= esched.date_end) 
      OR (esched.date_start <= '2010-09-25 00:00:00' 
       AND '2010-09-25 00:00:00' <= esched.date_end))) 

Может быть переписано как:

AND (

    //date_start is between range - fine 
    (esched.date_start BETWEEN '2010-09-01 00:00:00' AND '2010-09-25 00:00:00') 

    //date_end is between range - fine 
    OR (esched.date_end BETWEEN '2010-09-01 00:00:00' AND '2010-09-25 00:00:00')  

    OR (esched.date_start <= '2010-09-01 00:00:00' AND esched.date_end >= '2010-09-01 00:00:00') 

    OR (esched.date_start <= '2010-09-25 00:00:00' AND esched.date_end > = '2010-09-25 00:00:00') 
) 
+1

Я определенно использую индексы, вернусь сюда позже. –

+0

Я пытаюсь отфильтровать дату события, которая находится в пределах диапазона дат. например. Мероприятие - с 3 сентября по 5 сентября. Запрос с 3 по 4 сентября, с 4 по 6 сентября и с 1 по 3 сентября должен вернуть событие. –

+0

Как насчет запроса с 1 по 8 сентября, он должен вернуть событие, а также 4 сентября и 2 сентября –

2

на вашем обновлении вы упоминаете вы подозреваете проблему быть в финиковых фильтров.

Все эти проверки даты можно суммировать в одной проверки:

esched.date_ends >= '2010-09-01 00:00:00' and esched.date_start <= '2010-09-25 00:00:00' 

Если с над ним ведет себя так же, проверьте, быстро следующие возвраты/набирает свои показатели:

ВЫБОР COUNT (DISTINCT esched.course_id) FROM events_schedule esched WHERE esched.date_ends> = '2010-09-01 00:00:00' и esched.date_start < = '2010-09-25 00:00:00'

ps I думаю,, что при использовании соединения вы можете сделать SELECT COUNT (c.course_id), чтобы подсчитать основные записи курсов в запросе напрямую, т.е.


обновление повторно в настоящее время большую часть времени будет дикий поиск карты после изменения:

Используйте mysql full text search. Обязательно проверьте fulltext-restrictions, одним из важных является то, что он поддерживается только в таблицах MyISAM. Я должен сказать, что я действительно не использовал полнотекстовый поиск mysql, и я не уверен, как это влияет на использование других индексов в запросе.

Если вы не можете использовать полнотекстовый поиск, имхо вам не удастся использовать ваш текущий подход к нему, т. Е. Поскольку он не может использовать обычный индекс, чтобы проверить, содержится ли его слово в любой части текста ,

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

+0

Я обновил свой пост. –

+0

@geocine, если бы я следил за этим правом, это устранило проблему с фильтрами даты до типа% /, поэтому это улучшение, не так ли? – eglasius

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