There are some small pitfalls that you will have to pay attention to, because it depends on the indexes you are creating and/or dropping.
Along Come Clustered Indexes
There are tips out there that suggest to create clustered indexes on heaps (unsorted data) to allow them to be sorted (due to the creation of the clustered index) and to then remove the clustered index to then have a heap again. Rebuilding the table after dropping the index will free up some unused space due to records being deleted in pages.
Heaps (Tables without Clustered Indexes) (Microsoft | Learn).
To rebuild a heap to reclaim wasted space:
Create a clustered index on the heap, and then drop that clustered index.
Use the ALTER TABLE ... REBUILD command to rebuild the heap.
There is a small warning in the above article stating that creating and dropping a clustered index on a heap where other indexes are present will require a total rebuild of all non-clusterd indexes. CAUTION!
Creating or dropping clustered indexes requires rewriting the entire table. If the table has nonclustered indexes, all the nonclustered indexes must all be recreated whenever the clustered index is changed. Therefore, changing from a heap to a clustered index structure or back can take a lot of time and require disk space for reordering data in tempdb.
You could have a major performance impact if you created a clustered-index on a heap containing non-clustered indexes and then removing the clustered index again.
SQL Server Clustered Tables vs Heap Tables (MSSQLTips)
A clustered table provides a few benefits over a heap such as controlling how the data is sorted and stored, the ability to use the index to find rows quickly and the ability to reorganize the data by rebuilding the clustered index. Depending on INSERT, UPDATE and DELETE activity against your tables, your physical data can become very fragmented. This fragmentation can lead to wasted space in your database, because of partly full pages as well as the need to read more pages in order to satisfy the query. So what can be done?
The primary issue that we want to address is the fragmentation that occurs with normal database activity. Depending on whether your table has a clustered index or not will determine if you can easily address the fragmentation problem down to the physical data level. Because a heap or a clustered index determines the physical storage of your table data, there can only be one of these per table. So a table can either have one heap or one clustered index.
Removing a Clustered Index from a Heap (Table) will not return the now sorted data (due to the creation of the clustered index) into an unsorted state.
Answering Your Question
Does creating an index and then deleting it return the database to the pre-index creation state?
Not in all cases, as stated above. Adding and removing a clustered index to a heap may have a major impact on performance and may make a big difference on how your database reacts (execution plan-wise) to these changes.
Example Using db<>fiddle
Here is a short example that shows that creating a clustered-index on a heap and then dropping the clustered-index, will not return the data into its previous state. Even after a ALTER TABLE ... REBUILD
...
db<>fiddle example
create table [heap]
(
id int,
first_name nvarchar(10),
family_name nvarchar(20)
)
;
insert into [heap] (id, first_name, family_name)
values
(4,'John', 'Nautilus'),
(2,'Erik', 'Dreadnaught'),
(1, 'J.D.', 'Edwards')
;
3 rows affected
select * from [heap];
id |
first_name |
family_name |
4 |
John |
Nautilus |
2 |
Erik |
Dreadnaught |
1 |
J.D. |
Edwards |
create clustered index [cix_heap_family_name_PERF_20230321] on [heap] (family_name);
select * from [heap]; -- no longer a heap actually, but a clustered table
id |
first_name |
family_name |
2 |
Erik |
Dreadnaught |
1 |
J.D. |
Edwards |
4 |
John |
Nautilus |
drop index [cix_heap_family_name_PERF_20230321] on [heap];
select * from heap; -- now a sorted heap
id |
first_name |
family_name |
2 |
Erik |
Dreadnaught |
1 |
J.D. |
Edwards |
4 |
John |
Nautilus |
alter table [heap] rebuild;
select * from [heap];
id |
first_name |
family_name |
2 |
Erik |
Dreadnaught |
1 |
J.D. |
Edwards |
4 |
John |
Nautilus |
fiddle
The data has been altered!
Possible Solutions
- Backups -> Restores to development environment
- Database Snapshots in development environment
...and please don't create indexes in the production environment for quick testing.