diff options
author | Andreas Brandl <abrandl@gitlab.com> | 2018-10-28 19:16:47 +0100 |
---|---|---|
committer | Andreas Brandl <abrandl@gitlab.com> | 2018-12-03 21:26:50 +0100 |
commit | 3a7d9b4b02934c259fa2eda46143fa67320c2f5f (patch) | |
tree | 011da8a1dedf0da904f3c962ff3c90e46e869123 /spec/lib/gitlab/database | |
parent | dce4a92bb06ae58e08bf104acc9b47a57f62c0dd (diff) | |
download | gitlab-ce-3a7d9b4b02934c259fa2eda46143fa67320c2f5f.tar.gz |
Implement TablesampleCountStrategy.
A tablesample count executes in two phases:
* Estimate table sizes based on reltuples.
* Based on the estimate:
* If the table is considered 'small', execute an exact relation count.
* Otherwise, count on a sample of the table using TABLESAMPLE.
The size of the sample is chosen in a way that we always roughly scan
the same amount of rows (see TABLESAMPLE_ROW_TARGET).
Diffstat (limited to 'spec/lib/gitlab/database')
-rw-r--r-- | spec/lib/gitlab/database/count_spec.rb | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/spec/lib/gitlab/database/count_spec.rb b/spec/lib/gitlab/database/count_spec.rb index 699422abb6b..d6668cee23e 100644 --- a/spec/lib/gitlab/database/count_spec.rb +++ b/spec/lib/gitlab/database/count_spec.rb @@ -123,4 +123,57 @@ describe Gitlab::Database::Count do end end end + + describe Gitlab::Database::Count::TablesampleCountStrategy do + subject { strategy.count } + let(:strategy) { described_class.new(models) } + + describe '#count' do + let(:estimates) { { Project => threshold + 1, Identity => threshold - 1 } } + let(:threshold) { Gitlab::Database::Count::TablesampleCountStrategy::EXACT_COUNT_THRESHOLD } + + before do + allow(strategy).to receive(:size_estimates).with(check_statistics: false).and_return(estimates) + end + + context 'for tables with an estimated small size' do + it 'performs an exact count' do + expect(Identity).to receive(:count).and_call_original + + expect(subject).to include({ Identity => 1 }) + end + end + + context 'for tables with an estimated large size' do + it 'performs a tablesample count' do + expect(Project).not_to receive(:count) + + result = subject + expect(result[Project]).to eq(3) + end + end + + context 'insufficient permissions' do + it 'returns an empty hash' do + allow(strategy).to receive(:size_estimates).and_raise(PG::InsufficientPrivilege) + + expect(subject).to eq({}) + end + end + end + + describe '.enabled?' do + it 'is enabled for PostgreSQL' do + allow(Gitlab::Database).to receive(:postgresql?).and_return(true) + + expect(described_class.enabled?).to be_truthy + end + + it 'is disabled for MySQL' do + allow(Gitlab::Database).to receive(:postgresql?).and_return(false) + + expect(described_class.enabled?).to be_falsey + end + end + end end |