Зачем учитывать количество операций чтения и записи в таблицу
Что проверяют
Понимаете ли вы, что соотношение чтений и записей определяет почти все решения по таблице: индексы, кэш, реплики, схему. Следом обычно дают сценарий, например таблицу логов или справочник, и просят сказать, что вы с ней сделаете и почему.
Как отвечать
Сначала объясните, на что влияет соотношение:
- индексы: каждый ускоряет чтение, но обновляется при каждом
INSERT,UPDATEиDELETE. На таблице с частой записью лишний индекс стоит дороже выигрыша; - кэширование: оно разгружает чтение, а не запись. Справочник, который читают тысячи раз и меняют раз в день, идеален для
IMemoryCacheили Redis черезIDistributedCache. Часто меняемые данные в кэше приносят проблему инвалидации; - масштабирование: чтение масштабируется репликами, запись упирается в основной узел. При перекосе в чтение помогают реплики и CQRS, при перекосе в запись: пакетная вставка, партиционирование, очереди;
- блокировки: частые обновления одних и тех же строк создают конкуренцию и дедлоки, поэтому «горячие» счётчики выносят отдельно;
- деньги: в облачных базах вроде Cosmos DB или DynamoDB чтения и записи тарифицируются отдельно.
Затем покажите, как считать. В SQL Server есть sys.dm_db_index_usage_stats, где по каждому индексу видны чтения (user_seeks, user_scans, user_lookups) и записи (user_updates). В PostgreSQL то же дают pg_stat_user_tables и pg_stat_user_indexes. Со стороны приложения логирование EF Core через LogTo или профилировщик покажет, сколько запросов уходит на один HTTP-запрос.
Из EF Core полезно назвать: AsNoTracking для запросов только на чтение, пакетный SaveChanges, ExecuteUpdate и ExecuteDelete для массовых изменений без загрузки сущностей, SqlBulkCopy для больших вставок.
Где спотыкаются
Навешивают индекс под каждый отчёт на таблицу с интенсивной вставкой и удивляются, что запись просела.
Смотрят только на суммарные числа за сутки. Проблемы создают пики, поэтому смотреть нужно на нагрузку в час наибольшей активности.
Не замечают N+1: страница делает сотню мелких запросов вместо одного, и никакой индекс это не исправит, нужны Include или проекция.