Ответы пользователя по тегу SQL
  • Что почитать по оптимизации SQL запросов?

    @kshvakov
    Ответ написан
    Комментировать
  • Как получить JSON объект из PostgreSQL?

    @kshvakov
    Как-то так:

    select row_to_json(j.*) from (
    
    	select  'string' as parentTableFirstProp, to_json(
    
    		(
    		select to_json(array_agg(r.*)) from (
    			select s as childTableFirstProp from (select unnest('{another string,yet another string}'::text[]) as s) _
    		)as r
    		)
    	) as parentToChildReference
    
    ) as j
    Ответ написан
    2 комментария
  • Как заставить Postgres использовать индексы?

    @kshvakov
    Сделайте 2 таблицы, что то вроде

    create table core_keywords(
        keyword_id serial primary key,
        keyword    varchar(100)
    );
    create unique index u_idx_keyword on core_keywords(lower(keyword));
    create index t_idx_keywords on core_keywords using gin (lower(keyword) gin_trgm_ops);
    
    create table core_keywords_entry(
        keyword_id int not null references core_keywords,
        created_at timestamp with time zone not null default CURRENT_TIMESTAMP,
        primary key (keyword_id, created_at)
    );


    ну и будет все проще, что-то вроде

    select 
        e.keyword_id, 
        count(*) 
    from core_keywords_entry as e
    join core_keywords as k using(keyword_id)
    where lower(k.keyword) like  '%something%'
    group by 1
    Ответ написан
  • Как разделять логику запросов в СУБД и PHP?

    @kshvakov
    У всех разное понимание "правильно". По сути все сводится к "либо все, либо ничего".
    Если есть понимание как работает СУБД и её возможностей, вы скорее всего будете все выносить в нее: приложение будет туда только "ходить за данными" (дергать одну "хранимку" всесто кучи запросов), и записывать данные, опять же через "хранимку" и одним запросом вместо кучи. У нас даже "шедулеры" в самой БД (если они должны менять данные или что-то с ними делать).

    Либо вариант когда СУБД выступает как хранилище строк с продвинутыми возможностями типа вторичных ключей и индексов + более развесистый синтаксис на "селект", такое обычно с MySql в виду его "особенностей"
    Ответ написан
    Комментировать
  • Стоит ли использовать ltree в postgresql? И как лучше в ручную организовать древовидную структуру?

    @kshvakov
    Да, для постгреса используйте ltree: удобно, производительно
    Ответ написан
    Комментировать
  • Как оптимизаровать запрос в postgresql c фильтрацией и сортировкой?

    @kshvakov
    Вообще вся эта штука сильно зависит от селективности, если данных по value много постгрес может решить что "посортировать так" это эффективнее, в общем же случае индекс будет использоваться

    т.к. "настройки по-умолчанию" сами сделайте analyze для entities, т.к. скорее всего постгрес не в курсе как у вас там данные по таблице распределены и "полюет на все фулсканом"

    ps:

    create table entities (id serial, value int, date timestamp);
    
    create index idx_order on entities (value, date asc nulls last);
    
    
    insert into entities (value, date)
    select 
    generate_series(1, 20),
    time
    from generate_series(date_trunc('day', current_timestamp - '10 day'::interval), date_trunc('day', current_timestamp ), '1 second') as time;
    
    
    analyze entities;
    
    
    explain SELECT * FROM entities WHERE value = 10 ORDER BY date ASC NULLS LAST
    
    
    Sort  (cost=239331.74..241545.03 rows=885318 width=16)
      Sort Key: date
      ->  Bitmap Heap Scan on entities  (cost=32277.78..136750.25 rows=885318 width=16)
            Recheck Cond: (value = 10)
            ->  Bitmap Index Scan on idx_order  (cost=0.00..32056.45 rows=885318 width=0)
                  Index Cond: (value = 10)
    
    
    truncate entities;
    
    insert into entities (value, date)
    select 
    generate_series(1, 200),
    time
    from generate_series(date_trunc('day', current_timestamp - '1 day'::interval), date_trunc('day', current_timestamp ), '1 second') as time;
    
    analyze entities;
    
    
    explain SELECT * FROM entities WHERE value = 10 ORDER BY date ASC NULLS LAST;
    
    Sort  (cost=106726.86..106942.86 rows=86401 width=16)
      Sort Key: date
      ->  Bitmap Heap Scan on entities  (cost=3202.17..99642.51 rows=86401 width=16)
            Recheck Cond: (value = 10)
            ->  Bitmap Index Scan on idx_order  (cost=0.00..3180.57 rows=86401 width=0)
                  Index Cond: (value = 10)
    
    
    
    explain analyze SELECT * FROM entities WHERE value = 10 ORDER BY date ASC NULLS LAST;
    
    Sort  (cost=106726.86..106942.86 rows=86401 width=16) (actual time=18774.148..18783.923 rows=86401 loops=1)
      Sort Key: date
      Sort Method: external sort  Disk: 2200kB
      ->  Bitmap Heap Scan on entities  (cost=3202.17..99642.51 rows=86401 width=16) (actual time=2618.908..18681.170 rows=86401 loops=1)
            Recheck Cond: (value = 10)
            Rows Removed by Index Recheck: 9708392
            Heap Blocks: exact=33638 lossy=52763
            ->  Bitmap Index Scan on idx_order  (cost=0.00..3180.57 rows=86401 width=0) (actual time=2611.946..2611.946 rows=86401 loops=1)
                  Index Cond: (value = 10)
    Planning time: 0.093 ms
    Execution time: 18788.452 ms
    
    
    set work_mem='1GB';
    
    explain analyze SELECT * FROM entities WHERE value = 10 ORDER BY date ASC NULLS LAST;
    
    Sort  (cost=106726.86..106942.86 rows=86401 width=16) (actual time=614.335..619.024 rows=86401 loops=1)
      Sort Key: date
      Sort Method: quicksort  Memory: 7123kB
      ->  Bitmap Heap Scan on entities  (cost=3202.17..99642.51 rows=86401 width=16) (actual time=198.700..595.232 rows=86401 loops=1)
            Recheck Cond: (value = 10)
            Heap Blocks: exact=86401
            ->  Bitmap Index Scan on idx_order  (cost=0.00..3180.57 rows=86401 width=0) (actual time=177.392..177.392 rows=86401 loops=1)
                  Index Cond: (value = 10)
    Planning time: 0.145 ms
    Execution time: 623.327 ms
    Ответ написан
  • Как безопасно работать с sql?

    @kshvakov
    это напрямую зависит от используемого драйвера, go database/sql за это не отвечает https://golang.org/src/database/sql/sql.go?s=25224...

    можно сделать "драйвер" который какраз "заменяет значение через эскейпинг" и привет иньекция

    судя по плейсхолдеру это у вас mysql, если используете go-sql-driver то все ок

    https://github.com/go-sql-driver/mysql/blob/master...
    https://github.com/go-sql-driver/mysql/blob/master...

    он использует "подготовленный" запрос, на сервер "отдельно" уйдет запрос и отдельно данные, в запрос ничего драйвер не запихает
    Ответ написан
    8 комментариев