@Override
    public void prepare() throws ServiceNotProvidedException, ModuleStartException {
        jdbcClient = new JDBCClient(config.getProperties());
        modelInstaller = (JDBCTableInstaller) createModelInstaller();
        tableHelper = new TableHelper(getManager(), jdbcClient);

        this.registerServiceImplementation(
            StorageBuilderFactory.class,
            new StorageBuilderFactory.Default());

        this.registerServiceImplementation(
            IBatchDAO.class,
            new JDBCBatchDAO(
                jdbcClient,
                config.getMaxSizeOfBatchSql(),
                config.getAsyncBatchPersistentPoolSize()));
        this.registerServiceImplementation(
            StorageDAO.class,
            new JDBCStorageDAO(jdbcClient));

        this.registerServiceImplementation(
            INetworkAddressAliasDAO.class,
            new JDBCNetworkAddressAliasDAO(jdbcClient, getManager()));

        this.registerServiceImplementation(
            ITopologyQueryDAO.class,
            new JDBCTopologyQueryDAO(jdbcClient, tableHelper));
        this.registerServiceImplementation(
            IMetricsQueryDAO.class,
            new JDBCMetricsQueryDAO(jdbcClient, tableHelper));
        this.registerServiceImplementation(
            ITraceQueryDAO.class,
            new JDBCTraceQueryDAO(getManager(), jdbcClient, tableHelper));
        this.registerServiceImplementation(
            IBrowserLogQueryDAO.class,
            new JDBCBrowserLogQueryDAO(jdbcClient, tableHelper));
        this.registerServiceImplementation(
            IMetadataQueryDAO.class,
            new JDBCMetadataQueryDAO(jdbcClient, config.getMetadataQueryMaxSize(), getManager()));
        this.registerServiceImplementation(
            IAggregationQueryDAO.class,
            new JDBCAggregationQueryDAO(jdbcClient, tableHelper));
        this.registerServiceImplementation(
            IAlarmQueryDAO.class,
            new JDBCAlarmQueryDAO(jdbcClient, getManager(), tableHelper));
        this.registerServiceImplementation(
            IHistoryDeleteDAO.class,
            new JDBCHistoryDeleteDAO(jdbcClient, tableHelper, modelInstaller, Clock.systemDefaultZone()));
        this.registerServiceImplementation(
            IRecordsQueryDAO.class,
            new JDBCRecordsQueryDAO(jdbcClient, tableHelper));
        this.registerServiceImplementation(
            ILogQueryDAO.class,
            new JDBCLogQueryDAO(jdbcClient, getManager(), tableHelper));

        this.registerServiceImplementation(
            IProfileTaskQueryDAO.class,
            new JDBCProfileTaskQueryDAO(jdbcClient, getManager()));
        this.registerServiceImplementation(
            IProfileTaskLogQueryDAO.class,
            new JDBCProfileTaskLogQueryDAO(jdbcClient, tableHelper));
        this.registerServiceImplementation(
            IProfileThreadSnapshotQueryDAO.class,
            new JDBCProfileThreadSnapshotQueryDAO(jdbcClient, tableHelper));
        this.registerServiceImplementation(
            UITemplateManagementDAO.class,
            new JDBCUITemplateManagementDAO(jdbcClient, tableHelper));
        this.registerServiceImplementation(
            UIMenuManagementDAO.class,
            new JDBCUIMenuManagementDAO(jdbcClient, tableHelper));

        this.registerServiceImplementation(
            IEventQueryDAO.class,
            new JDBCEventQueryDAO(jdbcClient, tableHelper));

        this.registerServiceImplementation(
            IEBPFProfilingTaskDAO.class,
            new JDBCEBPFProfilingTaskDAO(jdbcClient, tableHelper)
        );
        this.registerServiceImplementation(
            IEBPFProfilingScheduleDAO.class,
            new JDBCEBPFProfilingScheduleDAO(jdbcClient, tableHelper)
        );
        this.registerServiceImplementation(
            IEBPFProfilingDataDAO.class,
            new JDBCEBPFProfilingDataDAO(jdbcClient, tableHelper)
        );
        this.registerServiceImplementation(
            IContinuousProfilingPolicyDAO.class,
            new JDBCContinuousProfilingPolicyDAO(jdbcClient, tableHelper)
        );
        this.registerServiceImplementation(
            IServiceLabelDAO.class,
            new JDBCServiceLabelQueryDAO(jdbcClient, tableHelper)
        );
        this.registerServiceImplementation(
            ITagAutoCompleteQueryDAO.class,
            new JDBCTagAutoCompleteQueryDAO(jdbcClient, tableHelper)
        );
        this.registerServiceImplementation(
            IZipkinQueryDAO.class,
            new JDBCZipkinQueryDAO(jdbcClient, tableHelper)
        );
        this.registerServiceImplementation(
            ISpanAttachedEventQueryDAO.class,
            new JDBCSpanAttachedEventQueryDAO(jdbcClient, tableHelper)
        );
        this.registerServiceImplementation(
            IHierarchyQueryDAO.class,
            new JDBCHierarchyQueryDAO(jdbcClient, config.getMetadataQueryMaxSize(), tableHelper)
        );
        this.registerServiceImplementation(
            IAsyncProfilerTaskQueryDAO.class,
            new JDBCAsyncProfilerTaskQueryDAO(jdbcClient, tableHelper)
        );
        this.registerServiceImplementation(
            IAsyncProfilerTaskLogQueryDAO.class,
            new JDBCAsyncProfilerTaskLogQueryDAO(jdbcClient, tableHelper)
        );
        this.registerServiceImplementation(
            IJFRDataQueryDAO.class,
            new JDBCJFRDataQueryDAO(jdbcClient, tableHelper)
        );
        this.registerServiceImplementation(
            StorageTTLStatusQuery.class,
            new DefaultStorageTTLStatusQuery()
        );
    }
Different storage implementations have different ways to create the tables/indices,
the specific implementations should provide a model installer for that storage.
oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/common/JDBCStorageProvider.java