Sly32

Рейтинг
372
Регистрация
29.03.2012
Решил на практике проверить разницу в скорости запросов. Использовал постгресс 16 с простой таблицей:
create table news
(
    id      serial
        primary key,
    title   varchar(30)  not null,
    content text         not null,
    slug    varchar(128) not null
);

alter table news
    owner to postgres;

create index idx_id_btree
    on news (id);

create index idx_slug_hash
    on news using hash (slug);

create index ix_news_id
    on news (id);
Добавил туда более 100 тысяч записей, и сделал код, ищущий записи по разным полям, обычный селект-where
@timer
    def get_news_by_id(self, n_id):
        stmt = (
            select(News)
            .where(News.id == n_id))
        with Session() as session:

            print("Get by ID"+"="*120)
            print(stmt)
            result = session.execute(stmt).one()
            print("Result:")
            print(result.News.id, result.News.title)
            
            
    @timer
    def get_news_by_slug(self, slug):
        stmt = (
            select(News)
            .where(News.slug == slug))
        with Session() as session:

            print("Get by slug: "+"="*120)
            print(stmt)
            result = session.execute(stmt).one()
            print("Result:")
            print(result.News.id, result.News.title)
            
            
    @timer
    def get_news_by_title(self, title):
        stmt = (
            select(News)
            .where(News.title == title))
        with Session() as session:

            print("Get by title: "+"="*120)
            print(stmt)
            result = session.execute(stmt).one()
            print("Result:")
            print(result.News.id, result.News.title)
И получил интересные результаты:

Get by ID========================================================================================================================
SELECT news.id, news.title, news.content, news.slug
FROM news
WHERE news.id = :id_1
Result:
109536 SdGRBUQoZfQDiUh3zTC0wUUzHicUvM
Execution time: 0.0937650203704834
Get by ID========================================================================================================================
SELECT news.id, news.title, news.content, news.slug
FROM news
WHERE news.id = :id_1
Result:
109536 SdGRBUQoZfQDiUh3zTC0wUUzHicUvM
Execution time: 0.006050825119018555
Get by slug: ========================================================================================================================
SELECT news.id, news.title, news.content, news.slug
FROM news
WHERE news.slug = :slug_1
Result:
109536 SdGRBUQoZfQDiUh3zTC0wUUzHicUvM
Execution time: 0.007730007171630859
Get by slug: ========================================================================================================================
SELECT news.id, news.title, news.content, news.slug
FROM news
WHERE news.slug = :slug_1
Result:
109536 SdGRBUQoZfQDiUh3zTC0wUUzHicUvM
Execution time: 0.005480051040649414
Get by title: ========================================================================================================================
SELECT news.id, news.title, news.content, news.slug
FROM news
WHERE news.title = :title_1
Result:
109536 SdGRBUQoZfQDiUh3zTC0wUUzHicUvM
Execution time: 0.015486001968383789
Get by title: ========================================================================================================================
SELECT news.id, news.title, news.content, news.slug
FROM news
WHERE news.title = :title_1
Result:
109536 SdGRBUQoZfQDiUh3zTC0wUUzHicUvM
Execution time: 0.012657880783081055

Process finished with exit code 0
результат 3 - по неиндексированному полю title - ожидаемо он на порядок меньше. А вот с айди и слагом интересно. Дело в том что первый запрос по айди, где для индексации используется винарное дерево - сильно просаживается по скорости, второй и последующий - такой же или немного быстрее чем поиск по текстовому полю с индексом в виде хэш
А хэш всегда стабилен по скорости, независимо от количества запросов. 
Кто-то может это обьяснить?


Aisamiery #:
Там если и будет разница, то фактически нивелироваться железом, вот табличка на 1.5kk записей

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

Sly32 #:
например site.com/4321-Novost.html, то есть новость будет выгребаться из базы не по текстовому ключу, а по идентификатору 4321

Я говорил про идеальный мир. А при использовании хэша и поиска по точному вхождению поиск по хэшируемому индексу будет быстрее. Потому что временная сложность поиска по бинарному дереву будет  O(log n) а для поиска по хэшу -О(1) для случая с хорошо разреженной тоблицы без коллизий, но даже для случая коллизий это будет  O(1 + k/n), где k - количество элементов в списке коллизий для данного хэша, а n - размер хэш-таблицы.

Aisamiery #:
Я вам задам другой вопрос, кто вам сказал что строки в индексе хранятся в виде строк? =))

В плане Постгрес это могут быть и b-tree, HASH, GIST,  но да - это все строковые данные, которые проигрывают по скорости b-tree с числами, конечно, зависит от вида поиска, например это точное совпадение или диапазон или полнотекст. 

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

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

chaturanga #:
Хешировать целое число неиденитичной функцией - явная изобыточность.

А разве индексы в БД это не массив хэшей? Тут избыточность мне кажется не причем...

Владимир #:

выборка из базы по строковому ключу "address "

OMG! ты реально не понимаешь что такое роутинг и думаешь: что если ты набрал в строке 

site.ru/address/

это сразу привело к тому что поехал запрос в БД???

API тебе ничего не говорит???

Владимир #:
для минимизации нагрузки на базу, новости должны работать через псевдо ЧПУ, то есть выгребаться они должны по идентификатору, но в адресе могут быть также человекопонятные фразы, например site.com/4321-Novost.html, то есть новость будет выгребаться из базы не по текстовому ключу, а по идентификатору 4321

Перечитал 3 раза и не понял о чем речь вообще? При чем тут ЧПУ и запросы в базу?

ЧПУ - это всего навсего роутинг, который перенаправляет на код, который будет делать запросы в БД, например. Как вы его оформляете - никакого значения не имеет в плане скорости. 

Иван Т #:
Картинки я так открывал.

попробуй понять разницу между движком сайта и его конфигами и контентом сайта. Ты можешь не знать не то что про движок - даже на каком языке написан сайт. Роботс  и тэги отвечают не за ВИДИМОСТЬ а за ИНДЕКСАЦИЮ в поисковых системах. 

Dmitriy_2014 #:
Ну я бы видел это так, жмешь кнопку сканируется база со статьями, анализируется и создаются супер релевантные связи, супер похожие, а профит в виде поднятия просмотров и удержания пользователей.

Я тебе такой алгоритм и описывал. Максимум 2 недели займет написать такое, ну и естественно, оплатить АПИшку. Но я не уверен что это будет сильно лучше чем сделать плагин на основе тэгов. Просто нужно будет тратить время каждый раз на их грамонтное прописание, ИИ это сделает за тебя.

Иван Т #:

Как как? Пишется в адресной строке "домен папка папка папка и сам файл вот так файл.пхп".

Ну попробуй )))

Всего: 7407